ega-v9 1.0.0 → 1.0.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/dist/index.js CHANGED
@@ -6,6 +6,163 @@ exports.replay = replay;
6
6
  exports.provenance = provenance;
7
7
  exports.contain = contain;
8
8
  const crypto_1 = require("crypto");
9
+ class EGAInputValidationError extends TypeError {
10
+ constructor(args) {
11
+ super(`[${args.code}] ${args.message}`);
12
+ this.name = "EGAInputValidationError";
13
+ this.code = args.code;
14
+ this.field = args.field;
15
+ this.expected = args.expected;
16
+ this.receivedType = describeInputType(args.value);
17
+ Object.setPrototypeOf(this, new.target.prototype);
18
+ }
19
+ }
20
+ function describeInputType(value) {
21
+ if (value === null) {
22
+ return "null";
23
+ }
24
+ if (Array.isArray(value)) {
25
+ return "array";
26
+ }
27
+ return typeof value;
28
+ }
29
+ function isPlainObject(value) {
30
+ if (value === null ||
31
+ typeof value !== "object" ||
32
+ Array.isArray(value)) {
33
+ return false;
34
+ }
35
+ const prototype = Object.getPrototypeOf(value);
36
+ return (prototype === Object.prototype ||
37
+ prototype === null);
38
+ }
39
+ function assertStandaloneInput(input, functionName) {
40
+ if (input === undefined) {
41
+ throw new EGAInputValidationError({
42
+ code: "EGA_INPUT_REQUIRED",
43
+ message: `${functionName} input is required. Pass a defined execution value.`,
44
+ value: input,
45
+ field: "input",
46
+ expected: "defined value"
47
+ });
48
+ }
49
+ }
50
+ function validateEGAOptions(options) {
51
+ if (!isPlainObject(options)) {
52
+ throw new EGAInputValidationError({
53
+ code: "EGA_OPTIONS_TYPE",
54
+ message: "EGA.init options must be a plain object.",
55
+ value: options,
56
+ field: "options",
57
+ expected: "plain object"
58
+ });
59
+ }
60
+ if (options.appName !== undefined &&
61
+ (typeof options.appName !== "string" ||
62
+ options.appName.trim().length === 0)) {
63
+ throw new EGAInputValidationError({
64
+ code: typeof options.appName === "string"
65
+ ? "EGA_OPTION_VALUE"
66
+ : "EGA_OPTION_TYPE",
67
+ message: "options.appName must be a non-empty string.",
68
+ value: options.appName,
69
+ field: "options.appName",
70
+ expected: "non-empty string"
71
+ });
72
+ }
73
+ if (options.trustLevel !== undefined &&
74
+ options.trustLevel !== "supported" &&
75
+ options.trustLevel !== "verified") {
76
+ throw new EGAInputValidationError({
77
+ code: "EGA_OPTION_VALUE",
78
+ message: 'options.trustLevel must be "supported" or "verified".',
79
+ value: options.trustLevel,
80
+ field: "options.trustLevel",
81
+ expected: '"supported" | "verified"'
82
+ });
83
+ }
84
+ for (const field of [
85
+ "telemetry",
86
+ "failClosed"
87
+ ]) {
88
+ const value = options[field];
89
+ if (value !== undefined &&
90
+ typeof value !== "boolean") {
91
+ throw new EGAInputValidationError({
92
+ code: "EGA_OPTION_TYPE",
93
+ message: `options.${field} must be a boolean.`,
94
+ value,
95
+ field: `options.${field}`,
96
+ expected: "boolean"
97
+ });
98
+ }
99
+ }
100
+ if (options.policyId !== undefined &&
101
+ (typeof options.policyId !== "string" ||
102
+ options.policyId.trim().length === 0)) {
103
+ throw new EGAInputValidationError({
104
+ code: typeof options.policyId === "string"
105
+ ? "EGA_OPTION_VALUE"
106
+ : "EGA_OPTION_TYPE",
107
+ message: "options.policyId must be a non-empty string.",
108
+ value: options.policyId,
109
+ field: "options.policyId",
110
+ expected: "non-empty string"
111
+ });
112
+ }
113
+ if (options.approvalThreshold !== undefined) {
114
+ if (typeof options.approvalThreshold !==
115
+ "number" ||
116
+ !Number.isFinite(options.approvalThreshold)) {
117
+ throw new EGAInputValidationError({
118
+ code: "EGA_OPTION_TYPE",
119
+ message: "options.approvalThreshold must be a finite number.",
120
+ value: options.approvalThreshold,
121
+ field: "options.approvalThreshold",
122
+ expected: "finite number from 0 to 100"
123
+ });
124
+ }
125
+ if (options.approvalThreshold < 0 ||
126
+ options.approvalThreshold > 100) {
127
+ throw new EGAInputValidationError({
128
+ code: "EGA_OPTION_RANGE",
129
+ message: "options.approvalThreshold must be between 0 and 100.",
130
+ value: options.approvalThreshold,
131
+ field: "options.approvalThreshold",
132
+ expected: "number from 0 to 100"
133
+ });
134
+ }
135
+ }
136
+ }
137
+ function validateGuardInvocation(req, res, next) {
138
+ if (!isPlainObject(req)) {
139
+ throw new EGAInputValidationError({
140
+ code: "EGA_GUARD_REQUEST_REQUIRED",
141
+ message: "EGA guard requires a request object.",
142
+ value: req,
143
+ field: "req",
144
+ expected: "request object"
145
+ });
146
+ }
147
+ if (!isPlainObject(res)) {
148
+ throw new EGAInputValidationError({
149
+ code: "EGA_GUARD_RESPONSE_REQUIRED",
150
+ message: "EGA guard requires a response object.",
151
+ value: res,
152
+ field: "res",
153
+ expected: "response object"
154
+ });
155
+ }
156
+ if (typeof next !== "function") {
157
+ throw new EGAInputValidationError({
158
+ code: "EGA_GUARD_NEXT_REQUIRED",
159
+ message: "EGA guard requires a next callback.",
160
+ value: next,
161
+ field: "next",
162
+ expected: "function"
163
+ });
164
+ }
165
+ }
9
166
  class EGA {
10
167
  constructor(options = {}) {
11
168
  this.eventLog = [];
@@ -20,10 +177,12 @@ class EGA {
20
177
  };
21
178
  }
22
179
  static init(options = {}) {
180
+ validateEGAOptions(options);
23
181
  return new EGA(options);
24
182
  }
25
183
  guard() {
26
184
  return (req, res, next) => {
185
+ validateGuardInvocation(req, res, next);
27
186
  const requestId = (0, crypto_1.randomUUID)();
28
187
  const clientIdentity = buildAnonymousClientIdentity(req, this.options.appName);
29
188
  const licenseState = evaluateLicenseState(req);
@@ -621,6 +780,7 @@ function stableStringify(input) {
621
780
  }).join(",")}}`;
622
781
  }
623
782
  function verifyExecution(input) {
783
+ assertStandaloneInput(input, "verifyExecution");
624
784
  const ega = EGA.init();
625
785
  const replayRoot = ega.replayRoot(input);
626
786
  const businessMetrics = collectBusinessMetrics(input);
@@ -680,12 +840,15 @@ function verifyExecution(input) {
680
840
  };
681
841
  }
682
842
  function replay(input) {
843
+ assertStandaloneInput(input, "replay");
683
844
  return verifyExecution(input);
684
845
  }
685
846
  function provenance(input) {
847
+ assertStandaloneInput(input, "provenance");
686
848
  return verifyExecution(input);
687
849
  }
688
850
  function contain(input) {
851
+ assertStandaloneInput(input, "contain");
689
852
  return verifyExecution(input);
690
853
  }
691
854
  function guardLatencyMicroseconds(startedAt) {
package/dist/index.mjs ADDED
@@ -0,0 +1,27 @@
1
+ "use strict compatibility wrapper";
2
+
3
+ import commonJsModule from "./index.js";
4
+
5
+ const {
6
+ EGA,
7
+ contain,
8
+ ega,
9
+ provenance,
10
+ replay,
11
+ verifyExecution,
12
+ } = commonJsModule;
13
+
14
+ export {
15
+ EGA,
16
+ contain,
17
+ ega,
18
+ provenance,
19
+ replay,
20
+ verifyExecution,
21
+ };
22
+
23
+ /*
24
+ * Preserve the historical Node.js ESM-to-CommonJS default-import
25
+ * compatibility behavior.
26
+ */
27
+ export default commonJsModule;
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "ega-v9",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "EGA V9 TypeScript SDK for replay, provenance, containment, and SCORP LOCK governance.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
7
  "files": [
8
8
  "dist",
9
9
  "README.md",
10
10
  "LICENSE"
11
11
  ],
12
12
  "scripts": {
13
- "build": "tsc",
13
+ "build": "tsc && node scripts/generate-esm-wrapper.cjs",
14
14
  "test": "npm run build && node ../../scripts/testing/run-v1-test-suite.cjs",
15
15
  "dev": "tsc --watch"
16
16
  },
@@ -35,5 +35,15 @@
35
35
  "homepage": "https://github.com/paibyun9/EGA-V9#readme",
36
36
  "bugs": {
37
37
  "url": "https://github.com/paibyun9/EGA-V9/issues"
38
+ },
39
+ "module": "./dist/index.mjs",
40
+ "exports": {
41
+ ".": {
42
+ "types": "./dist/index.d.ts",
43
+ "import": "./dist/index.mjs",
44
+ "require": "./dist/index.js",
45
+ "default": "./dist/index.js"
46
+ },
47
+ "./package.json": "./package.json"
38
48
  }
39
49
  }