@excofy/utils 1.0.15 → 2.1.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.
@@ -20,9 +20,6 @@ jobs:
20
20
  - name: Install Dependencies
21
21
  run: npm ci
22
22
 
23
- - name: Lint Code
24
- run: npm run lint
25
-
26
23
  - name: Build Package
27
24
  run: npm run build
28
25
 
package/dist/index.cjs CHANGED
@@ -446,6 +446,15 @@ function createValidator() {
446
446
  }
447
447
  return validator;
448
448
  },
449
+ sanitizeAlphanumeric() {
450
+ if (shouldSkipValidation()) return validator;
451
+ if (typeof current.value === "string") {
452
+ const cleaned = current.value.replace(/[^A-Za-z0-9]/g, "").trim();
453
+ current.value = cleaned;
454
+ current.inputs[current.field] = cleaned;
455
+ }
456
+ return validator;
457
+ },
449
458
  sanitizeDigits() {
450
459
  if (shouldSkipValidation()) return validator;
451
460
  if (typeof current.value === "string") {
@@ -720,9 +729,24 @@ var decryptPayload = async ({
720
729
  );
721
730
  return decoder.decode(buffer);
722
731
  };
732
+ async function generateDeterministicHash(code, secret) {
733
+ const key = await crypto.subtle.importKey(
734
+ "raw",
735
+ encoder.encode(secret),
736
+ { name: "HMAC", hash: "SHA-256" },
737
+ false,
738
+ ["sign"]
739
+ );
740
+ const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(code));
741
+ return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
742
+ }
743
+ async function verifyDeterministicHash(inputCode, storedHash, secret) {
744
+ const hash = await generateDeterministicHash(inputCode, secret);
745
+ return hash === storedHash;
746
+ }
723
747
  var cryptoUtils = {
724
748
  uuidV4: () => crypto.randomUUID(),
725
- hash: async (password, salt) => {
749
+ hash: async (password, salt = 10) => {
726
750
  const importedKey = await crypto.subtle.importKey(
727
751
  "raw",
728
752
  encoder.encode(password),
@@ -798,7 +822,9 @@ var cryptoUtils = {
798
822
  return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
799
823
  },
800
824
  encryptPayload,
801
- decryptPayload
825
+ decryptPayload,
826
+ generateDeterministicHash,
827
+ verifyDeterministicHash
802
828
  };
803
829
 
804
830
  // src/helpers/slug.ts
package/dist/index.d.cts CHANGED
@@ -32,6 +32,7 @@ interface ValidatorField {
32
32
  slug(message: string): ValidatorField;
33
33
  sanitize(): ValidatorField;
34
34
  sanitizeAlphaSpaces(): ValidatorField;
35
+ sanitizeAlphanumeric(): ValidatorField;
35
36
  sanitizeDigits(): ValidatorField;
36
37
  sanitizePreservingNewlines(): ValidatorField;
37
38
  sanitizeHTML(tags?: AllowedTag[]): ValidatorField;
@@ -132,6 +133,8 @@ interface ICrypto {
132
133
  AUTH_PAYLOAD_SECRET: string;
133
134
  token: string;
134
135
  }) => Promise<string>;
136
+ generateDeterministicHash: (code: string, secret: string) => Promise<string>;
137
+ verifyDeterministicHash: (inputCode: string, storedHash: string, secret: string) => Promise<boolean>;
135
138
  }
136
139
  declare const cryptoUtils: ICrypto;
137
140
 
package/dist/index.d.ts CHANGED
@@ -32,6 +32,7 @@ interface ValidatorField {
32
32
  slug(message: string): ValidatorField;
33
33
  sanitize(): ValidatorField;
34
34
  sanitizeAlphaSpaces(): ValidatorField;
35
+ sanitizeAlphanumeric(): ValidatorField;
35
36
  sanitizeDigits(): ValidatorField;
36
37
  sanitizePreservingNewlines(): ValidatorField;
37
38
  sanitizeHTML(tags?: AllowedTag[]): ValidatorField;
@@ -132,6 +133,8 @@ interface ICrypto {
132
133
  AUTH_PAYLOAD_SECRET: string;
133
134
  token: string;
134
135
  }) => Promise<string>;
136
+ generateDeterministicHash: (code: string, secret: string) => Promise<string>;
137
+ verifyDeterministicHash: (inputCode: string, storedHash: string, secret: string) => Promise<boolean>;
135
138
  }
136
139
  declare const cryptoUtils: ICrypto;
137
140
 
package/dist/index.js CHANGED
@@ -410,6 +410,15 @@ function createValidator() {
410
410
  }
411
411
  return validator;
412
412
  },
413
+ sanitizeAlphanumeric() {
414
+ if (shouldSkipValidation()) return validator;
415
+ if (typeof current.value === "string") {
416
+ const cleaned = current.value.replace(/[^A-Za-z0-9]/g, "").trim();
417
+ current.value = cleaned;
418
+ current.inputs[current.field] = cleaned;
419
+ }
420
+ return validator;
421
+ },
413
422
  sanitizeDigits() {
414
423
  if (shouldSkipValidation()) return validator;
415
424
  if (typeof current.value === "string") {
@@ -684,9 +693,24 @@ var decryptPayload = async ({
684
693
  );
685
694
  return decoder.decode(buffer);
686
695
  };
696
+ async function generateDeterministicHash(code, secret) {
697
+ const key = await crypto.subtle.importKey(
698
+ "raw",
699
+ encoder.encode(secret),
700
+ { name: "HMAC", hash: "SHA-256" },
701
+ false,
702
+ ["sign"]
703
+ );
704
+ const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(code));
705
+ return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
706
+ }
707
+ async function verifyDeterministicHash(inputCode, storedHash, secret) {
708
+ const hash = await generateDeterministicHash(inputCode, secret);
709
+ return hash === storedHash;
710
+ }
687
711
  var cryptoUtils = {
688
712
  uuidV4: () => crypto.randomUUID(),
689
- hash: async (password, salt) => {
713
+ hash: async (password, salt = 10) => {
690
714
  const importedKey = await crypto.subtle.importKey(
691
715
  "raw",
692
716
  encoder.encode(password),
@@ -762,7 +786,9 @@ var cryptoUtils = {
762
786
  return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
763
787
  },
764
788
  encryptPayload,
765
- decryptPayload
789
+ decryptPayload,
790
+ generateDeterministicHash,
791
+ verifyDeterministicHash
766
792
  };
767
793
 
768
794
  // src/helpers/slug.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@excofy/utils",
3
- "version": "1.0.15",
3
+ "version": "2.1.0",
4
4
  "description": "Biblioteca de utilitários para o Excofy",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -25,6 +25,12 @@ interface ICrypto {
25
25
  AUTH_PAYLOAD_SECRET: string;
26
26
  token: string;
27
27
  }) => Promise<string>;
28
+ generateDeterministicHash: (code: string, secret: string) => Promise<string>;
29
+ verifyDeterministicHash: (
30
+ inputCode: string,
31
+ storedHash: string,
32
+ secret: string
33
+ ) => Promise<boolean>;
28
34
  }
29
35
 
30
36
  /* --------------------- Helpers básicos --------------------- */
@@ -94,11 +100,55 @@ const decryptPayload = async ({
94
100
  return decoder.decode(buffer);
95
101
  };
96
102
 
103
+ /* --------------------- Hash (generate/verify) --------------------- */
104
+ /**
105
+ * Gera um hash determinístico (HMAC) a partir de um código e um segredo.
106
+ *
107
+ * @param code
108
+ * @param secret
109
+ * @returns
110
+ */
111
+ export async function generateDeterministicHash(
112
+ code: string,
113
+ secret: string
114
+ ): Promise<string> {
115
+ const key = await crypto.subtle.importKey(
116
+ 'raw',
117
+ encoder.encode(secret),
118
+ { name: 'HMAC', hash: 'SHA-256' },
119
+ false,
120
+ ['sign']
121
+ );
122
+
123
+ const signature = await crypto.subtle.sign('HMAC', key, encoder.encode(code));
124
+
125
+ return Array.from(new Uint8Array(signature))
126
+ .map((b) => b.toString(16).padStart(2, '0'))
127
+ .join('');
128
+ }
129
+
130
+ /**
131
+ * Verifica se o hash gerado a partir do código e segredo bate com o hash armazenado.
132
+ *
133
+ * @param inputCode
134
+ * @param storedHash
135
+ * @param secret
136
+ * @returns
137
+ */
138
+ export async function verifyDeterministicHash(
139
+ inputCode: string,
140
+ storedHash: string,
141
+ secret: string
142
+ ): Promise<boolean> {
143
+ const hash = await generateDeterministicHash(inputCode, secret);
144
+ return hash === storedHash;
145
+ }
146
+
97
147
  /* --------------------- Main API --------------------- */
98
148
  export const cryptoUtils: ICrypto = {
99
149
  uuidV4: (): string => crypto.randomUUID(),
100
150
 
101
- hash: async (password: string, salt: number): Promise<string> => {
151
+ hash: async (password: string, salt: number = 10): Promise<string> => {
102
152
  const importedKey = await crypto.subtle.importKey(
103
153
  'raw',
104
154
  encoder.encode(password),
@@ -199,4 +249,7 @@ export const cryptoUtils: ICrypto = {
199
249
 
200
250
  encryptPayload,
201
251
  decryptPayload,
252
+
253
+ generateDeterministicHash,
254
+ verifyDeterministicHash,
202
255
  };
@@ -39,6 +39,7 @@ interface ValidatorField {
39
39
  slug(message: string): ValidatorField;
40
40
  sanitize(): ValidatorField;
41
41
  sanitizeAlphaSpaces(): ValidatorField;
42
+ sanitizeAlphanumeric(): ValidatorField;
42
43
  sanitizeDigits(): ValidatorField;
43
44
  sanitizePreservingNewlines(): ValidatorField;
44
45
  sanitizeHTML(tags?: AllowedTag[]): ValidatorField;
@@ -421,6 +422,20 @@ export function createValidator<
421
422
  return validator;
422
423
  },
423
424
 
425
+ sanitizeAlphanumeric() {
426
+ if (shouldSkipValidation()) return validator;
427
+
428
+ if (typeof current.value === 'string') {
429
+ const cleaned = current.value
430
+ .replace(/[^A-Za-z0-9]/g, '') // remove tudo que não é letra ou número
431
+ .trim();
432
+ current.value = cleaned;
433
+ current.inputs[current.field] = cleaned as TRaw[keyof TRaw];
434
+ }
435
+
436
+ return validator;
437
+ },
438
+
424
439
  sanitizeDigits() {
425
440
  if (shouldSkipValidation()) return validator;
426
441