@ibiliaze/stringman 3.7.0 → 3.9.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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './seat';
1
2
  /**
2
3
  * Clean up extra whitespace in a string.
3
4
  *
@@ -142,11 +143,7 @@ export declare const invalidPw: (password: string, passwordLength?: number) => s
142
143
  export declare const b36: (n: number) => string;
143
144
  export declare const luhn36: (s: string) => string;
144
145
  export declare const ticket: {
145
- getTicketId: ({ fixtureId, sectionName, seatName, }: {
146
- fixtureId: string;
147
- sectionName: string;
148
- seatName: string;
149
- }) => string;
146
+ getTicketId: any;
150
147
  buildTicketCode: (args: {
151
148
  venueCode: string;
152
149
  fixtureLocalIso: string;
@@ -154,9 +151,10 @@ export declare const ticket: {
154
151
  row: number;
155
152
  col: number;
156
153
  rndLen?: number;
154
+ dashed?: boolean;
157
155
  }) => string;
158
156
  validateTicketCode: (code: string) => boolean;
159
- rndBlock: (len?: number) => string;
160
- fixtureBlock: (fixtureLocalIso: string) => string;
161
- seatBlock: (sectionId: string, row: number, col: number, len?: number) => string;
157
+ rndBlock: any;
158
+ fixtureBlock: any;
159
+ seatBlock: any;
162
160
  };
package/dist/index.js CHANGED
@@ -1,6 +1,21 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
17
  exports.ticket = exports.luhn36 = exports.b36 = exports.invalidPw = exports.getPublicIP = exports.isVideoUrl = exports.getRandomString = exports.extractImageSrcs = exports.select = exports.query = exports.getCloudinaryPublicId = exports.dp = exports.megaTrim = exports.superTrim = void 0;
18
+ __exportStar(require("./seat"), exports);
4
19
  const ticket_1 = require("./ticket");
5
20
  /**
6
21
  * Clean up extra whitespace in a string.
package/dist/seat.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare const getSeatRowFromName: (seatName: string) => string;
2
+ export declare const getSeatColFromName: (seatName: string) => string;
3
+ export declare const seatMapKey: (row: number, col: number) => string;
4
+ export declare const getItemId: (fixtureId: string, sectionId: string, seatId: string) => string;
5
+ export declare const getFromItemId: (itemId: string) => {
6
+ fixtureId: string;
7
+ sectionId: string;
8
+ seatId: string;
9
+ };
package/dist/seat.js ADDED
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFromItemId = exports.getItemId = exports.seatMapKey = exports.getSeatColFromName = exports.getSeatRowFromName = void 0;
4
+ const getSeatRowFromName = (seatName) => seatName?.split(':')?.[0];
5
+ exports.getSeatRowFromName = getSeatRowFromName;
6
+ const getSeatColFromName = (seatName) => seatName?.split(':')?.[1];
7
+ exports.getSeatColFromName = getSeatColFromName;
8
+ const seatMapKey = (row, col) => `${row}:${col}`;
9
+ exports.seatMapKey = seatMapKey;
10
+ const getItemId = (fixtureId, sectionId, seatId) => JSON.stringify({ fixtureId, sectionId, seatId });
11
+ exports.getItemId = getItemId;
12
+ const getFromItemId = (itemId) => JSON.parse(itemId);
13
+ exports.getFromItemId = getFromItemId;
package/dist/ticket.d.ts CHANGED
@@ -1,6 +1,18 @@
1
- export declare const seatBlock: (sectionId: string, row: number, col: number, len?: number) => string;
2
- export declare const fixtureBlock: (fixtureLocalIso: string) => string;
3
- export declare const rndBlock: (len?: number) => string;
1
+ export declare const luhn10: (digits: string) => string;
2
+ export declare const venueBlockNum: (venueCode: string, len?: number) => string;
3
+ export declare const seatBlockNum: (sectionId: string, row: number, col: number, len?: number) => string;
4
+ export declare const fixtureBlockNum: (fixtureLocalIso: string, len?: number) => string;
5
+ export declare const rndBlockNum: (len?: number) => string;
6
+ export declare const buildTicketCodeNumeric: (args: {
7
+ venueCode: string;
8
+ fixtureLocalIso: string;
9
+ sectionId: string;
10
+ row: number;
11
+ col: number;
12
+ rndLen?: number;
13
+ dashed?: boolean;
14
+ }) => string;
15
+ export declare const validateTicketCodeNumeric: (code: string) => boolean;
4
16
  export declare const buildTicketCode: (args: {
5
17
  venueCode: string;
6
18
  fixtureLocalIso: string;
@@ -8,10 +20,6 @@ export declare const buildTicketCode: (args: {
8
20
  row: number;
9
21
  col: number;
10
22
  rndLen?: number;
23
+ dashed?: boolean;
11
24
  }) => string;
12
25
  export declare const validateTicketCode: (code: string) => boolean;
13
- export declare const getTicketId: ({ fixtureId, sectionName, seatName, }: {
14
- fixtureId: string;
15
- sectionName: string;
16
- seatName: string;
17
- }) => string;
package/dist/ticket.js CHANGED
@@ -1,78 +1,115 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTicketId = exports.validateTicketCode = exports.buildTicketCode = exports.rndBlock = exports.fixtureBlock = exports.seatBlock = void 0;
3
+ exports.validateTicketCode = exports.buildTicketCode = exports.validateTicketCodeNumeric = exports.buildTicketCodeNumeric = exports.rndBlockNum = exports.fixtureBlockNum = exports.seatBlockNum = exports.venueBlockNum = exports.luhn10 = void 0;
4
4
  const node_crypto_1 = require("node:crypto");
5
- const _1 = require(".");
6
- const seatBlock = (sectionId, row, col, len = 3) => {
5
+ // ---------- helpers ----------
6
+ const pad = (n, len) => n.toString().padStart(len, '0');
7
+ // Luhn mod-10 for digits
8
+ const luhn10 = (digits) => {
9
+ let sum = 0;
10
+ let dbl = false;
11
+ for (let i = digits.length - 1; i >= 0; i--) {
12
+ let d = digits.charCodeAt(i) - 48; // '0' -> 48
13
+ if (dbl) {
14
+ d *= 2;
15
+ if (d > 9)
16
+ d -= 9;
17
+ }
18
+ sum += d;
19
+ dbl = !dbl;
20
+ }
21
+ const check = (10 - (sum % 10)) % 10;
22
+ return String(check);
23
+ };
24
+ exports.luhn10 = luhn10;
25
+ // ---------- numeric blocks ----------
26
+ const venueBlockNum = (venueCode, len = 2) => {
7
27
  try {
8
- const h = (0, node_crypto_1.createHash)('sha1').update(`${sectionId}:${row}:${col}`).digest(); // 20 bytes
9
- // take first 2 bytes -> 0..65535
10
- const n = (h[0] << 8) | h[1];
11
- const code = (0, _1.b36)(n).padStart(3, '0'); // 3 chars base36
12
- return code.slice(-len);
28
+ // Small, stable hash of the code -> 0..(10^len - 1)
29
+ const h = (0, node_crypto_1.createHash)('sha1').update(venueCode.toUpperCase()).digest(); // 20 bytes
30
+ const n = ((h[0] << 8) | h[1]) % 10 ** len;
31
+ return pad(n, len);
13
32
  }
14
- catch (e) {
15
- return '';
33
+ catch {
34
+ return ''.padStart(len, '0');
16
35
  }
17
36
  };
18
- exports.seatBlock = seatBlock;
19
- // Fixture datetime block (local TZ string -> YYMMDDhhmm -> base36)
20
- const fixtureBlock = (fixtureLocalIso) => {
37
+ exports.venueBlockNum = venueBlockNum;
38
+ const seatBlockNum = (sectionId, row, col, len = 3) => {
21
39
  try {
22
- // fixtureLocalIso like "2025-10-31T20:00" in venue TZ (no Z)
40
+ // Hash -> 16-bit -> modulo 10^len
41
+ const h = (0, node_crypto_1.createHash)('sha1').update(`${sectionId}:${row}:${col}`).digest();
42
+ const n16 = (h[0] << 8) | h[1];
43
+ const n = n16 % 10 ** len;
44
+ return pad(n, len);
45
+ }
46
+ catch {
47
+ return ''.padStart(len, '0');
48
+ }
49
+ };
50
+ exports.seatBlockNum = seatBlockNum;
51
+ const fixtureBlockNum = (fixtureLocalIso, len = 6) => {
52
+ try {
53
+ // Expect "YYYY-MM-DDThh:mm" (local, no Z).
23
54
  const m = fixtureLocalIso.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})/);
24
55
  if (!m)
25
56
  throw new Error('Bad fixtureLocalIso');
26
57
  const [_, y, M, d, h, mnt] = m;
27
- const compact = `${y.slice(2)}${M}${d}${h}${mnt}`; // YYMMDDhhmm as number
28
- return (0, _1.b36)(Number(compact)).padStart(5, '0'); // ~5-6 chars
58
+ // YYMMDDhhmm is 10 digits; compress to len digits via mod 10^len.
59
+ const compact = Number(`${y.slice(2)}${M}${d}${h}${mnt}`); // e.g. 2510312000
60
+ const n = compact % 10 ** len;
61
+ return pad(n, len);
29
62
  }
30
- catch (e) {
31
- return '';
63
+ catch {
64
+ return ''.padStart(len, '0');
32
65
  }
33
66
  };
34
- exports.fixtureBlock = fixtureBlock;
35
- // Random block
36
- const rndBlock = (len = 3) => {
67
+ exports.fixtureBlockNum = fixtureBlockNum;
68
+ const rndBlockNum = (len = 3) => {
37
69
  try {
38
- // 16-bit random -> base36 3-4 chars
39
- const n = (0, node_crypto_1.randomBytes)(2).readUInt16BE(0);
40
- return (0, _1.b36)(n).padStart(3, '0').slice(-len);
70
+ // Uniform cryptographic integer in [0, 10^len)
71
+ const max = 10 ** len;
72
+ return pad((0, node_crypto_1.randomInt)(0, max), len);
41
73
  }
42
- catch (e) {
43
- return '';
74
+ catch {
75
+ return ''.padStart(len, '0');
44
76
  }
45
77
  };
46
- exports.rndBlock = rndBlock;
47
- const buildTicketCode = (args) => {
78
+ exports.rndBlockNum = rndBlockNum;
79
+ // ---------- builder & validator (numeric-only) ----------
80
+ const buildTicketCodeNumeric = (args) => {
48
81
  try {
49
- const VV = args.venueCode.toUpperCase().slice(0, 2);
50
- const E = (0, exports.fixtureBlock)(args.fixtureLocalIso); // 5-6 chars
51
- const S = (0, exports.seatBlock)(args.sectionId, args.row, args.col, 3); // 3 chars
52
- const R = (0, exports.rndBlock)(args.rndLen ?? 3); // 3 chars
53
- const body = `${VV}${E}${S}${R}`;
54
- const C = (0, _1.luhn36)(body);
55
- // Format with dashes for readability (optional)
82
+ const VV = (0, exports.venueBlockNum)(args.venueCode, 2); // 2 digits
83
+ const E = (0, exports.fixtureBlockNum)(args.fixtureLocalIso, 6); // 6 digits
84
+ const S = (0, exports.seatBlockNum)(args.sectionId, args.row, args.col); // 3 digits
85
+ const R = (0, exports.rndBlockNum)(args.rndLen ?? 3); // 3 digits
86
+ const body = `${VV}${E}${S}${R}`; // 14 digits
87
+ const C = (0, exports.luhn10)(body); // 1 digit
88
+ const numeric = `${body}${C}`; // 15 digits total
89
+ if (args.dashed === false)
90
+ return numeric;
91
+ // Grouping 2-6-3-3-1 for readability
56
92
  return `${VV}-${E}-${S}-${R}-${C}`;
57
93
  }
58
- catch (e) {
94
+ catch {
59
95
  return '';
60
96
  }
61
97
  };
62
- exports.buildTicketCode = buildTicketCode;
63
- const validateTicketCode = (code) => {
98
+ exports.buildTicketCodeNumeric = buildTicketCodeNumeric;
99
+ const validateTicketCodeNumeric = (code) => {
64
100
  try {
65
- const clean = code.replace(/-/g, '').toUpperCase();
66
- if (!/^[0-9A-Z]{12,14}$/.test(clean))
67
- return false;
101
+ const clean = code.replace(/-/g, '');
102
+ if (!/^\d{15}$/.test(clean))
103
+ return false; // 2+6+3+3+1
68
104
  const body = clean.slice(0, -1);
69
105
  const check = clean.slice(-1);
70
- return (0, _1.luhn36)(body) === check;
106
+ return (0, exports.luhn10)(body) === check;
71
107
  }
72
- catch (e) {
108
+ catch {
73
109
  return false;
74
110
  }
75
111
  };
76
- exports.validateTicketCode = validateTicketCode;
77
- const getTicketId = ({ fixtureId, sectionName, seatName, }) => `${sectionName}-${seatName}-${fixtureId}`;
78
- exports.getTicketId = getTicketId;
112
+ exports.validateTicketCodeNumeric = validateTicketCodeNumeric;
113
+ // ---------- compatibility shim (if you want same names as before) ----------
114
+ exports.buildTicketCode = exports.buildTicketCodeNumeric;
115
+ exports.validateTicketCode = exports.validateTicketCodeNumeric;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@ibiliaze/stringman",
3
- "version": "3.7.0",
3
+ "version": "3.9.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
9
  "pub": "npm publish --access public",
10
- "git": "git add .; git commit -m 'changes'; git tag -a v3.7.0 -m 'v3.7.0'; git push origin v3.7.0; git push",
10
+ "git": "git add .; git commit -m 'changes'; git tag -a v3.9.0 -m 'v3.9.0'; git push origin v3.9.0; git push",
11
11
  "push": "npm run build; npm run git; npm run pub"
12
12
  },
13
13
  "author": "Ibi Hasanli",
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './seat';
1
2
  import { buildTicketCode, fixtureBlock, getTicketId, rndBlock, seatBlock, validateTicketCode } from './ticket';
2
3
 
3
4
  /**
package/src/seat.ts ADDED
@@ -0,0 +1,10 @@
1
+ export const getSeatRowFromName = (seatName: string) => seatName?.split(':')?.[0];
2
+ export const getSeatColFromName = (seatName: string) => seatName?.split(':')?.[1];
3
+
4
+ export const seatMapKey = (row: number, col: number) => `${row}:${col}`;
5
+
6
+ export const getItemId = (fixtureId: string, sectionId: string, seatId: string) =>
7
+ JSON.stringify({ fixtureId, sectionId, seatId });
8
+
9
+ export const getFromItemId = (itemId: string): { fixtureId: string; sectionId: string; seatId: string } =>
10
+ JSON.parse(itemId);
package/src/ticket.ts CHANGED
@@ -1,83 +1,114 @@
1
- import { createHash, randomBytes } from 'node:crypto';
2
- import { b36, luhn36 } from '.';
1
+ import { createHash, randomInt } from 'node:crypto';
3
2
 
4
- export const seatBlock = (sectionId: string, row: number, col: number, len = 3) => {
3
+ // ---------- helpers ----------
4
+ const pad = (n: number, len: number) => n.toString().padStart(len, '0');
5
+
6
+ // Luhn mod-10 for digits
7
+ export const luhn10 = (digits: string): string => {
8
+ let sum = 0;
9
+ let dbl = false;
10
+ for (let i = digits.length - 1; i >= 0; i--) {
11
+ let d = digits.charCodeAt(i) - 48; // '0' -> 48
12
+ if (dbl) {
13
+ d *= 2;
14
+ if (d > 9) d -= 9;
15
+ }
16
+ sum += d;
17
+ dbl = !dbl;
18
+ }
19
+ const check = (10 - (sum % 10)) % 10;
20
+ return String(check);
21
+ };
22
+
23
+ // ---------- numeric blocks ----------
24
+ export const venueBlockNum = (venueCode: string, len = 2) => {
5
25
  try {
6
- const h = createHash('sha1').update(`${sectionId}:${row}:${col}`).digest(); // 20 bytes
7
- // take first 2 bytes -> 0..65535
8
- const n = (h[0] << 8) | h[1];
9
- const code = b36(n).padStart(3, '0'); // 3 chars base36
10
- return code.slice(-len);
11
- } catch (e) {
12
- return '';
26
+ // Small, stable hash of the code -> 0..(10^len - 1)
27
+ const h = createHash('sha1').update(venueCode.toUpperCase()).digest(); // 20 bytes
28
+ const n = ((h[0] << 8) | h[1]) % 10 ** len;
29
+ return pad(n, len);
30
+ } catch {
31
+ return ''.padStart(len, '0');
13
32
  }
14
33
  };
15
34
 
16
- // Fixture datetime block (local TZ string -> YYMMDDhhmm -> base36)
17
- export const fixtureBlock = (fixtureLocalIso: string) => {
35
+ export const seatBlockNum = (sectionId: string, row: number, col: number, len = 3) => {
18
36
  try {
19
- // fixtureLocalIso like "2025-10-31T20:00" in venue TZ (no Z)
37
+ // Hash -> 16-bit -> modulo 10^len
38
+ const h = createHash('sha1').update(`${sectionId}:${row}:${col}`).digest();
39
+ const n16 = (h[0] << 8) | h[1];
40
+ const n = n16 % 10 ** len;
41
+ return pad(n, len);
42
+ } catch {
43
+ return ''.padStart(len, '0');
44
+ }
45
+ };
46
+
47
+ export const fixtureBlockNum = (fixtureLocalIso: string, len = 6) => {
48
+ try {
49
+ // Expect "YYYY-MM-DDThh:mm" (local, no Z).
20
50
  const m = fixtureLocalIso.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})/);
21
51
  if (!m) throw new Error('Bad fixtureLocalIso');
22
52
  const [_, y, M, d, h, mnt] = m;
23
- const compact = `${y.slice(2)}${M}${d}${h}${mnt}`; // YYMMDDhhmm as number
24
- return b36(Number(compact)).padStart(5, '0'); // ~5-6 chars
25
- } catch (e) {
26
- return '';
53
+ // YYMMDDhhmm is 10 digits; compress to len digits via mod 10^len.
54
+ const compact = Number(`${y.slice(2)}${M}${d}${h}${mnt}`); // e.g. 2510312000
55
+ const n = compact % 10 ** len;
56
+ return pad(n, len);
57
+ } catch {
58
+ return ''.padStart(len, '0');
27
59
  }
28
60
  };
29
61
 
30
- // Random block
31
- export const rndBlock = (len = 3) => {
62
+ export const rndBlockNum = (len = 3) => {
32
63
  try {
33
- // 16-bit random -> base36 3-4 chars
34
- const n = randomBytes(2).readUInt16BE(0);
35
- return b36(n).padStart(3, '0').slice(-len);
36
- } catch (e) {
37
- return '';
64
+ // Uniform cryptographic integer in [0, 10^len)
65
+ const max = 10 ** len;
66
+ return pad(randomInt(0, max), len);
67
+ } catch {
68
+ return ''.padStart(len, '0');
38
69
  }
39
70
  };
40
71
 
41
- export const buildTicketCode = (args: {
42
- venueCode: string; // "SB"
72
+ // ---------- builder & validator (numeric-only) ----------
73
+ export const buildTicketCodeNumeric = (args: {
74
+ venueCode: string; // e.g. "SB"
43
75
  fixtureLocalIso: string; // "2025-10-31T20:00" in venue TZ
44
76
  sectionId: string;
45
77
  row: number;
46
78
  col: number;
47
- rndLen?: number; // 3 or 4
79
+ rndLen?: number; // default 3 (use 4 if you want more entropy)
80
+ dashed?: boolean; // default true (format with dashes)
48
81
  }) => {
49
82
  try {
50
- const VV = args.venueCode.toUpperCase().slice(0, 2);
51
- const E = fixtureBlock(args.fixtureLocalIso); // 5-6 chars
52
- const S = seatBlock(args.sectionId, args.row, args.col, 3); // 3 chars
53
- const R = rndBlock(args.rndLen ?? 3); // 3 chars
54
- const body = `${VV}${E}${S}${R}`;
55
- const C = luhn36(body);
56
- // Format with dashes for readability (optional)
83
+ const VV = venueBlockNum(args.venueCode, 2); // 2 digits
84
+ const E = fixtureBlockNum(args.fixtureLocalIso, 6); // 6 digits
85
+ const S = seatBlockNum(args.sectionId, args.row, args.col); // 3 digits
86
+ const R = rndBlockNum(args.rndLen ?? 3); // 3 digits
87
+
88
+ const body = `${VV}${E}${S}${R}`; // 14 digits
89
+ const C = luhn10(body); // 1 digit
90
+ const numeric = `${body}${C}`; // 15 digits total
91
+
92
+ if (args.dashed === false) return numeric;
93
+ // Grouping 2-6-3-3-1 for readability
57
94
  return `${VV}-${E}-${S}-${R}-${C}`;
58
- } catch (e) {
95
+ } catch {
59
96
  return '';
60
97
  }
61
98
  };
62
99
 
63
- export const validateTicketCode = (code: string) => {
100
+ export const validateTicketCodeNumeric = (code: string) => {
64
101
  try {
65
- const clean = code.replace(/-/g, '').toUpperCase();
66
- if (!/^[0-9A-Z]{12,14}$/.test(clean)) return false;
102
+ const clean = code.replace(/-/g, '');
103
+ if (!/^\d{15}$/.test(clean)) return false; // 2+6+3+3+1
67
104
  const body = clean.slice(0, -1);
68
105
  const check = clean.slice(-1);
69
- return luhn36(body) === check;
70
- } catch (e) {
106
+ return luhn10(body) === check;
107
+ } catch {
71
108
  return false;
72
109
  }
73
110
  };
74
111
 
75
- export const getTicketId = ({
76
- fixtureId,
77
- sectionName,
78
- seatName,
79
- }: {
80
- fixtureId: string;
81
- sectionName: string;
82
- seatName: string;
83
- }) => `${sectionName}-${seatName}-${fixtureId}`;
112
+ // ---------- compatibility shim (if you want same names as before) ----------
113
+ export const buildTicketCode = buildTicketCodeNumeric;
114
+ export const validateTicketCode = validateTicketCodeNumeric;