genkode 1.1.0 → 1.2.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.
@@ -0,0 +1,60 @@
1
+ name: CI/CD Pipeline
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - 'feature/**'
7
+ - master
8
+ pull_request:
9
+ branches:
10
+ - master
11
+
12
+ jobs:
13
+ build-and-test:
14
+ name: Build & Test
15
+ runs-on: ubuntu-latest
16
+
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Setup Node
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: 22
25
+
26
+ - name: Install dependencies
27
+ run: npm install
28
+
29
+ - name: Build project
30
+ run: npm run build
31
+
32
+ - name: Run tests
33
+ run: npm test
34
+
35
+ publish:
36
+ name: Publish to npm
37
+ runs-on: ubuntu-latest
38
+ needs: build-and-test
39
+ if: github.ref == 'refs/heads/master'
40
+
41
+ steps:
42
+ - name: Checkout code
43
+ uses: actions/checkout@v4
44
+
45
+ - name: Setup Node
46
+ uses: actions/setup-node@v4
47
+ with:
48
+ node-version: 22
49
+ registry-url: https://registry.npmjs.org/
50
+
51
+ - name: Install dependencies
52
+ run: npm install
53
+
54
+ - name: Build project
55
+ run: npm run build
56
+
57
+ - name: Publish to npm
58
+ run: npm publish
59
+ env:
60
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md CHANGED
@@ -26,37 +26,30 @@ npm install genkode
26
26
  import { generateCode } from 'genkode';
27
27
 
28
28
  generateCode({ length: 12 });
29
- // Example: aZ8kL2pQ9xW1
29
+ // Example: rqfvYxJRWfoP (alpha by default)
30
30
 
31
- generateCode({ length: 12, type: "alpha" });
32
- // Example: rqfvYxJRWfoP
31
+ generateCode({ length: 12, type: "alphanumeric" });
32
+ // Example: aZ8kL2pQ9xW1
33
33
 
34
34
  generateCode({ length: 12, type: "numeric" });
35
35
  // Example: 362128126198
36
- ```
37
-
38
- ---
39
-
40
- ### Simple helper functions
41
36
 
42
- ```ts
43
- import { randomString, randomAlpha, randomNumeric } from 'genkode';
44
-
45
- randomString(12); // alphanumeric
46
- randomAlpha(12); // alphabets only
47
- randomNumeric(12); // numbers only
37
+ // Cryptographically secure generation
38
+ generateCode({ length: 12, type: "alphanumeric", secure: true });
39
+ // Example: Tz3mW8qA1nXp
48
40
  ```
49
41
 
50
42
  ---
51
43
 
52
44
  ## ⚙️ API
53
45
 
54
- ### generateCode(options)
46
+ ### `generateCode(options)`
55
47
 
56
- | Property | Type | Description |
57
- |----------|------|-------------|
58
- | length | number | Required length of string |
59
- | type | "alpha" \| "numeric" \| "alphanumeric" | Optional (default: alphanumeric) |
48
+ | Property | Type | Default | Description |
49
+ |----------|------|---------|-------------|
50
+ | `length` | `number` | — | Required. Length of the generated string |
51
+ | `type` | `"alpha"` \| `"numeric"` \| `"alphanumeric"` | `"alpha"` | Character set to use |
52
+ | `secure` | `boolean` | `false` | Use `crypto.getRandomValues` for cryptographically secure output |
60
53
 
61
54
  ---
62
55
 
@@ -67,6 +60,7 @@ randomNumeric(12); // numbers only
67
60
  - TypeScript support
68
61
  - Simple and flexible API
69
62
  - Multiple formats (alpha, numeric, alphanumeric)
63
+ - Optional cryptographically secure mode via Web Crypto API
70
64
 
71
65
  ---
72
66
 
@@ -80,10 +74,15 @@ randomNumeric(12); // numbers only
80
74
 
81
75
  ---
82
76
 
83
- ## 🔒 Notes
77
+ ## 🔒 Security
78
+
79
+ By default, `generateCode` uses `Math.random`, which is fast but **not cryptographically secure**.
84
80
 
85
- - Uses Math.random (not cryptographically secure)
86
- - Suitable for general-purpose usage
81
+ Set `secure: true` to use `crypto.getRandomValues` (Web Crypto API), which produces unbiased, cryptographically secure output. Use this when generating tokens, API keys, or any value where predictability is a security concern.
82
+
83
+ ```ts
84
+ generateCode({ length: 32, type: "alphanumeric", secure: true });
85
+ ```
87
86
 
88
87
  ---
89
88
 
@@ -98,4 +97,4 @@ https://www.npmjs.com/package/node-mumble
98
97
 
99
98
  ## 📄 License
100
99
 
101
- MIT
100
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,6 +1,3 @@
1
- import type { GenerateCodeOptions } from "./kode.interface.js";
2
- export declare function generateCode({ length, type }: GenerateCodeOptions): string;
3
- export declare function randomString(length: number): string;
4
- export declare function randomAlpha(length: number): string;
5
- export declare function randomNumeric(length: number): string;
1
+ import type { GenerateOptions } from "./kode.interface.js";
2
+ export declare function generateCode({ length, type, secure }: GenerateOptions): string;
6
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAmB/D,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,IAAqB,EAAE,EAAE,mBAAmB,GAAG,MAAM,CAI3F;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAmD3D,wBAAgB,YAAY,CAAC,EAAC,MAAM,EAAC,IAAc,EAAC,MAAc,EAAC,EAAE,eAAe,GAAG,MAAM,CAS5F"}
package/dist/index.js CHANGED
@@ -11,20 +11,34 @@ function generate(length, charset) {
11
11
  }
12
12
  return result;
13
13
  }
14
- export function generateCode({ length, type = "alphanumeric" }) {
15
- if (type === "alpha")
16
- return generate(length, ALPHA);
17
- if (type === "numeric")
18
- return generate(length, NUMERIC);
19
- return generate(length, ALPHANUM);
14
+ function generateSecure(length, charset) {
15
+ const max = charset.length;
16
+ const result = [];
17
+ const randomBuffer = new Uint8Array(1);
18
+ while (result.length < length) {
19
+ crypto.getRandomValues(randomBuffer);
20
+ const byte = randomBuffer[0];
21
+ if (byte < Math.floor(256 / max) * max) {
22
+ result.push(charset[byte % max]);
23
+ }
24
+ }
25
+ return result.join("");
20
26
  }
21
- export function randomString(length) {
27
+ function randomString(length) {
22
28
  return generate(length, ALPHANUM);
23
29
  }
24
- export function randomAlpha(length) {
30
+ function randomAlpha(length) {
25
31
  return generate(length, ALPHA);
26
32
  }
27
- export function randomNumeric(length) {
33
+ function randomNumeric(length) {
28
34
  return generate(length, NUMERIC);
29
35
  }
36
+ export function generateCode({ length, type = "alpha", secure = false }) {
37
+ const charset = type === "alpha" ? ALPHA :
38
+ type === "numeric" ? NUMERIC :
39
+ ALPHANUM;
40
+ return secure
41
+ ? generateSecure(length, charset)
42
+ : generate(length, charset);
43
+ }
30
44
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAG,sDAAsD,CAAC;AACrE,MAAM,OAAO,GAAG,YAAY,CAAC;AAC7B,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;AAEjC,SAAS,QAAQ,CAAC,MAAc,EAAE,OAAe;IAC/C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAE3B,OAAO,MAAM,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;QAC9C,MAAM,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;QACzB,MAAM,EAAE,CAAC;IACX,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,GAAG,cAAc,EAAuB;IACjF,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzD,OAAO,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAG,sDAAsD,CAAC;AACrE,MAAM,OAAO,GAAG,YAAY,CAAC;AAC7B,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;AAEjC,SAAS,QAAQ,CAAC,MAAc,EAAE,OAAe;IAC/C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAE3B,OAAO,MAAM,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;QAC9C,MAAM,IAAI,OAAO,CAAC,KAAK,CAAE,CAAC;QAC1B,MAAM,EAAE,CAAC;IACX,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAGD,SAAS,cAAc,CAAC,MAAc,EAAE,OAAe;IACrD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAEvC,OAAO,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;QAC9B,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAE,CAAC;QAE9B,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,GAAG,CAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzB,CAAC;AAGD,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,aAAa,CAAC,MAAc;IACnC,OAAO,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACnC,CAAC;AAGD,MAAM,UAAU,YAAY,CAAC,EAAC,MAAM,EAAC,IAAI,GAAG,OAAO,EAAC,MAAM,GAAG,KAAK,EAAkB;IAClF,MAAM,OAAO,GACX,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC9B,QAAQ,CAAC;IAEX,OAAO,MAAM;QACX,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC;QACjC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAChC,CAAC"}
@@ -1,5 +1,7 @@
1
- export interface GenerateCodeOptions {
1
+ export type CodeType = "alpha" | "numeric" | "alphanumeric";
2
+ export interface GenerateOptions {
2
3
  length: number;
3
- type?: "alpha" | "numeric" | "alphanumeric";
4
+ type?: CodeType;
5
+ secure?: boolean;
4
6
  }
5
7
  //# sourceMappingURL=kode.interface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kode.interface.d.ts","sourceRoot":"","sources":["../kode.interface.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,cAAc,CAAC;CAC7C"}
1
+ {"version":3,"file":"kode.interface.d.ts","sourceRoot":"","sources":["../kode.interface.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,cAAc,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB"}
package/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { GenerateCodeOptions } from "./kode.interface.js";
1
+ import type { GenerateOptions } from "./kode.interface.js";
2
2
 
3
3
  const ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
4
4
  const NUMERIC = "0123456789";
@@ -10,27 +10,52 @@ function generate(length: number, charset: string): string {
10
10
 
11
11
  while (length > 0) {
12
12
  const index = Math.floor(Math.random() * max);
13
- result += charset[index];
13
+ result += charset[index]!;
14
14
  length--;
15
15
  }
16
16
 
17
17
  return result;
18
18
  }
19
19
 
20
- export function generateCode({ length, type = "alphanumeric" }: GenerateCodeOptions): string {
21
- if (type === "alpha") return generate(length, ALPHA);
22
- if (type === "numeric") return generate(length, NUMERIC);
23
- return generate(length, ALPHANUM);
20
+
21
+ function generateSecure(length: number, charset: string): string {
22
+ const max = charset.length;
23
+ const result: string[] = [];
24
+ const randomBuffer = new Uint8Array(1);
25
+
26
+ while (result.length < length) {
27
+ crypto.getRandomValues(randomBuffer);
28
+ const byte = randomBuffer[0]!;
29
+
30
+ if (byte < Math.floor(256 / max) * max) {
31
+ result.push(charset[byte % max]!);
32
+ }
33
+ }
34
+
35
+ return result.join("");
24
36
  }
25
37
 
26
- export function randomString(length: number): string {
38
+
39
+ function randomString(length: number): string {
27
40
  return generate(length, ALPHANUM);
28
41
  }
29
42
 
30
- export function randomAlpha(length: number): string {
43
+ function randomAlpha(length: number): string {
31
44
  return generate(length, ALPHA);
32
45
  }
33
46
 
34
- export function randomNumeric(length: number): string {
47
+ function randomNumeric(length: number): string {
35
48
  return generate(length, NUMERIC);
36
49
  }
50
+
51
+
52
+ export function generateCode({length,type = "alpha",secure = false}: GenerateOptions): string {
53
+ const charset =
54
+ type === "alpha" ? ALPHA :
55
+ type === "numeric" ? NUMERIC :
56
+ ALPHANUM;
57
+
58
+ return secure
59
+ ? generateSecure(length, charset)
60
+ : generate(length, charset);
61
+ }
package/kode.interface.ts CHANGED
@@ -1,4 +1,7 @@
1
- export interface GenerateCodeOptions {
1
+ export type CodeType = "alpha" | "numeric" | "alphanumeric";
2
+
3
+ export interface GenerateOptions {
2
4
  length: number;
3
- type?: "alpha" | "numeric" | "alphanumeric";
5
+ type?: CodeType;
6
+ secure?: boolean;
4
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "genkode",
3
- "version": "1.1.0",
4
- "description": "A node package that creates a random unique characters string (Typescript Supported)",
3
+ "version": "1.2.0",
4
+ "description": "A lightweight Node.js utility to generate random alphanumeric, alphabetic, or numeric strings.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "repository": {
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "type": "module",
12
12
  "scripts": {
13
+ "test": "node --test",
13
14
  "build": "tsc",
14
15
  "prepublishOnly": "npm run build"
15
16
  },
@@ -36,6 +37,7 @@
36
37
  "author": "",
37
38
  "license": "MIT",
38
39
  "devDependencies": {
40
+ "@types/node": "^25.5.0",
39
41
  "tsx": "^4.21.0",
40
42
  "txc": "^0.0.1",
41
43
  "typescript": "^6.0.2"
@@ -43,5 +45,8 @@
43
45
  "bugs": {
44
46
  "url": "https://github.com/sammitpal/genkode/issues"
45
47
  },
46
- "homepage": "https://github.com/sammitpal/genkode#readme"
48
+ "homepage": "https://github.com/sammitpal/genkode#readme",
49
+ "dependencies": {
50
+ "crypto": "^1.0.1"
51
+ }
47
52
  }
@@ -0,0 +1,64 @@
1
+ /// <reference types="node" />
2
+ import test from "node:test";
3
+ import assert from "node:assert";
4
+ import { generateCode } from "../dist/index.js";
5
+
6
+ // Helper regex
7
+ const alphaRegex = /^[A-Za-z]+$/;
8
+ const numericRegex = /^[0-9]+$/;
9
+ const alphanumRegex = /^[A-Za-z0-9]+$/;
10
+
11
+ test("should generate string of correct length", () => {
12
+ const result = generateCode({ length: 20 });
13
+ assert.strictEqual(result.length, 20);
14
+ });
15
+
16
+ test("should generate alphabet-only string", () => {
17
+ const result = generateCode({ length: 30, type: "alpha" });
18
+ assert.ok(alphaRegex.test(result));
19
+ });
20
+
21
+ test("should generate numeric-only string", () => {
22
+ const result = generateCode({ length: 30, type: "numeric" });
23
+ assert.ok(numericRegex.test(result));
24
+ });
25
+
26
+ test("should generate alphanumeric string", () => {
27
+ const result = generateCode({ length: 30, type: "alphanumeric" });
28
+ assert.ok(alphanumRegex.test(result));
29
+ });
30
+
31
+ test("should generate secure string (alpha)", () => {
32
+ const result = generateCode({ length: 25, type: "alpha", secure: true });
33
+ assert.strictEqual(result.length, 25);
34
+ assert.ok(alphaRegex.test(result));
35
+ });
36
+
37
+ test("should generate secure numeric string", () => {
38
+ const result = generateCode({ length: 25, type: "numeric", secure: true });
39
+ assert.strictEqual(result.length, 25);
40
+ assert.ok(numericRegex.test(result));
41
+ });
42
+
43
+ test("should generate secure alphanumeric string", () => {
44
+ const result = generateCode({ length: 25, type: "alphanumeric", secure: true });
45
+ assert.strictEqual(result.length, 25);
46
+ assert.ok(alphanumRegex.test(result));
47
+ });
48
+
49
+ test("should generate different values each time (non-deterministic)", () => {
50
+ const a = generateCode({ length: 20 });
51
+ const b = generateCode({ length: 20 });
52
+
53
+ assert.notStrictEqual(a, b);
54
+ });
55
+
56
+ test("should handle small length", () => {
57
+ const result = generateCode({ length: 1 });
58
+ assert.strictEqual(result.length, 1);
59
+ });
60
+
61
+ test("should handle large length", () => {
62
+ const result = generateCode({ length: 1000 });
63
+ assert.strictEqual(result.length, 1000);
64
+ });
package/tsconfig.json CHANGED
@@ -3,23 +3,29 @@
3
3
  "rootDir": ".",
4
4
  "outDir": "./dist",
5
5
 
6
- "module": "nodenext",
7
- "target": "esnext",
8
- "types": [],
6
+ "module": "NodeNext",
7
+ "moduleResolution": "NodeNext",
8
+ "target": "ES2022",
9
+
10
+ "types": ["node"],
9
11
 
10
12
  "sourceMap": true,
11
13
  "declaration": true,
12
14
  "declarationMap": true,
13
15
 
16
+ "strict": true,
14
17
  "noUncheckedIndexedAccess": true,
15
18
  "exactOptionalPropertyTypes": true,
16
19
 
17
-
18
- "strict": true,
19
20
  "verbatimModuleSyntax": true,
20
21
  "isolatedModules": true,
21
22
  "noUncheckedSideEffectImports": true,
22
23
  "moduleDetection": "force",
23
- "skipLibCheck": true,
24
- }
25
- }
24
+
25
+ "skipLibCheck": true
26
+ },
27
+
28
+ "include": ["index.ts"],
29
+
30
+ "exclude": ["test", "dist", "node_modules"]
31
+ }