@tewtawanc/loops-utils 1.0.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,140 @@
1
+ /**
2
+ * @tewtawanc/loops-utils
3
+ *
4
+ * Shared utilities for Loops warehouse management system.
5
+ *
6
+ * SKU Generation:
7
+ * - Inventory SKU: Product specifications (grade, lot, material, weight, package)
8
+ * - Stock SKU: Physical units with location tracking
9
+ *
10
+ * @example
11
+ * import { generateInventorySku, generateStockSku } from '@tewtawanc/loops-utils';
12
+ *
13
+ * const sku = generateInventorySku({
14
+ * grade: 'HD6600B',
15
+ * lotNumber: 'H5490205B',
16
+ * materialCode: 'C/P',
17
+ * netWeight: 25,
18
+ * packageType: 'PALLET'
19
+ * });
20
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET"
21
+ */
22
+ interface InventorySkuParams {
23
+ materialCode: string;
24
+ grade: string;
25
+ lotNumber: string;
26
+ netWeight: number;
27
+ packageType: string;
28
+ }
29
+ interface StockSkuParams extends InventorySkuParams {
30
+ stockNumber: string;
31
+ }
32
+ /**
33
+ * Normalize SKU component to ensure valid SKU string:
34
+ * - Trims whitespace from both ends
35
+ * - Converts to uppercase for consistency
36
+ * - Replaces spaces with underscores
37
+ * - Removes special characters except / (for codes like C/P) and _ (word separator)
38
+ * - Removes consecutive underscores
39
+ * - Removes leading/trailing underscores
40
+ */
41
+ declare function normalizeSkuComponent(component: string): string;
42
+ /**
43
+ * Format weight with appropriate precision
44
+ * - Integer weights: "25"
45
+ * - Decimal weights: "25.5"
46
+ */
47
+ declare function formatWeight(weight: number): string;
48
+ /**
49
+ * Generate SKU for logical Inventory
50
+ * Format: {grade}-{lotNumber}-{materialCode}-{netWeight}KG-{packageType}
51
+ *
52
+ * @example
53
+ * generateInventorySku({
54
+ * materialCode: 'C/P',
55
+ * grade: 'HD6600B',
56
+ * lotNumber: 'H5490205B',
57
+ * netWeight: 25.0,
58
+ * packageType: 'PALLET'
59
+ * })
60
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET"
61
+ */
62
+ declare function generateInventorySku(params: InventorySkuParams): string;
63
+ /**
64
+ * Generate SKU for physical Stock
65
+ * Format: {inventorySKU}-{stockNumber}
66
+ *
67
+ * @example
68
+ * generateStockSku({
69
+ * materialCode: 'C/P',
70
+ * grade: 'HD6600B',
71
+ * lotNumber: 'H5490205B',
72
+ * netWeight: 25.0,
73
+ * packageType: 'PALLET',
74
+ * stockNumber: 'P001234'
75
+ * })
76
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET-P001234"
77
+ */
78
+ declare function generateStockSku(params: StockSkuParams): string;
79
+ /**
80
+ * Parse an Inventory SKU into its components
81
+ *
82
+ * @example
83
+ * parseInventorySku('HD6600B-H5490205B-C/P-25KG-PALLET')
84
+ * // Returns: {
85
+ * // materialCode: 'C/P',
86
+ * // grade: 'HD6600B',
87
+ * // lotNumber: 'H5490205B',
88
+ * // netWeight: 25.0,
89
+ * // packageType: 'PALLET'
90
+ * // }
91
+ */
92
+ declare function parseInventorySku(sku: string): InventorySkuParams | null;
93
+ /**
94
+ * Parse a Stock SKU into its components
95
+ *
96
+ * @example
97
+ * parseStockSku('HD6600B-H5490205B-C/P-25KG-PALLET-P001234')
98
+ * // Returns: {
99
+ * // materialCode: 'C/P',
100
+ * // grade: 'HD6600B',
101
+ * // lotNumber: 'H5490205B',
102
+ * // netWeight: 25.0,
103
+ * // packageType: 'PALLET',
104
+ * // stockNumber: 'P001234'
105
+ * // }
106
+ */
107
+ declare function parseStockSku(sku: string): StockSkuParams | null;
108
+ /**
109
+ * Extract inventory SKU from stock SKU
110
+ *
111
+ * @example
112
+ * extractInventorySku('HD6600B-H5490205B-C/P-25KG-PALLET-P001234')
113
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET"
114
+ */
115
+ declare function extractInventorySku(stockSku: string): string | null;
116
+ /**
117
+ * Validate if a string is a valid Inventory SKU format
118
+ */
119
+ declare function isValidInventorySku(sku: string): boolean;
120
+ /**
121
+ * Validate if a string is a valid Stock SKU format
122
+ */
123
+ declare function isValidStockSku(sku: string): boolean;
124
+ /**
125
+ * Generate a human-readable name from SKU components
126
+ * Format: {grade} {lotNumber} {materialCode} {netWeight}kg {packageType}
127
+ *
128
+ * @example
129
+ * generateInventoryName({
130
+ * materialCode: 'C/P',
131
+ * grade: 'HD6600B',
132
+ * lotNumber: 'H5490205B',
133
+ * netWeight: 25.0,
134
+ * packageType: 'PALLET'
135
+ * })
136
+ * // Returns: "HD6600B H5490205B C/P 25kg Pallet"
137
+ */
138
+ declare function generateInventoryName(params: InventorySkuParams): string;
139
+
140
+ export { type InventorySkuParams, type StockSkuParams, extractInventorySku, formatWeight, generateInventoryName, generateInventorySku, generateStockSku, isValidInventorySku, isValidStockSku, normalizeSkuComponent, parseInventorySku, parseStockSku };
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @tewtawanc/loops-utils
3
+ *
4
+ * Shared utilities for Loops warehouse management system.
5
+ *
6
+ * SKU Generation:
7
+ * - Inventory SKU: Product specifications (grade, lot, material, weight, package)
8
+ * - Stock SKU: Physical units with location tracking
9
+ *
10
+ * @example
11
+ * import { generateInventorySku, generateStockSku } from '@tewtawanc/loops-utils';
12
+ *
13
+ * const sku = generateInventorySku({
14
+ * grade: 'HD6600B',
15
+ * lotNumber: 'H5490205B',
16
+ * materialCode: 'C/P',
17
+ * netWeight: 25,
18
+ * packageType: 'PALLET'
19
+ * });
20
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET"
21
+ */
22
+ interface InventorySkuParams {
23
+ materialCode: string;
24
+ grade: string;
25
+ lotNumber: string;
26
+ netWeight: number;
27
+ packageType: string;
28
+ }
29
+ interface StockSkuParams extends InventorySkuParams {
30
+ stockNumber: string;
31
+ }
32
+ /**
33
+ * Normalize SKU component to ensure valid SKU string:
34
+ * - Trims whitespace from both ends
35
+ * - Converts to uppercase for consistency
36
+ * - Replaces spaces with underscores
37
+ * - Removes special characters except / (for codes like C/P) and _ (word separator)
38
+ * - Removes consecutive underscores
39
+ * - Removes leading/trailing underscores
40
+ */
41
+ declare function normalizeSkuComponent(component: string): string;
42
+ /**
43
+ * Format weight with appropriate precision
44
+ * - Integer weights: "25"
45
+ * - Decimal weights: "25.5"
46
+ */
47
+ declare function formatWeight(weight: number): string;
48
+ /**
49
+ * Generate SKU for logical Inventory
50
+ * Format: {grade}-{lotNumber}-{materialCode}-{netWeight}KG-{packageType}
51
+ *
52
+ * @example
53
+ * generateInventorySku({
54
+ * materialCode: 'C/P',
55
+ * grade: 'HD6600B',
56
+ * lotNumber: 'H5490205B',
57
+ * netWeight: 25.0,
58
+ * packageType: 'PALLET'
59
+ * })
60
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET"
61
+ */
62
+ declare function generateInventorySku(params: InventorySkuParams): string;
63
+ /**
64
+ * Generate SKU for physical Stock
65
+ * Format: {inventorySKU}-{stockNumber}
66
+ *
67
+ * @example
68
+ * generateStockSku({
69
+ * materialCode: 'C/P',
70
+ * grade: 'HD6600B',
71
+ * lotNumber: 'H5490205B',
72
+ * netWeight: 25.0,
73
+ * packageType: 'PALLET',
74
+ * stockNumber: 'P001234'
75
+ * })
76
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET-P001234"
77
+ */
78
+ declare function generateStockSku(params: StockSkuParams): string;
79
+ /**
80
+ * Parse an Inventory SKU into its components
81
+ *
82
+ * @example
83
+ * parseInventorySku('HD6600B-H5490205B-C/P-25KG-PALLET')
84
+ * // Returns: {
85
+ * // materialCode: 'C/P',
86
+ * // grade: 'HD6600B',
87
+ * // lotNumber: 'H5490205B',
88
+ * // netWeight: 25.0,
89
+ * // packageType: 'PALLET'
90
+ * // }
91
+ */
92
+ declare function parseInventorySku(sku: string): InventorySkuParams | null;
93
+ /**
94
+ * Parse a Stock SKU into its components
95
+ *
96
+ * @example
97
+ * parseStockSku('HD6600B-H5490205B-C/P-25KG-PALLET-P001234')
98
+ * // Returns: {
99
+ * // materialCode: 'C/P',
100
+ * // grade: 'HD6600B',
101
+ * // lotNumber: 'H5490205B',
102
+ * // netWeight: 25.0,
103
+ * // packageType: 'PALLET',
104
+ * // stockNumber: 'P001234'
105
+ * // }
106
+ */
107
+ declare function parseStockSku(sku: string): StockSkuParams | null;
108
+ /**
109
+ * Extract inventory SKU from stock SKU
110
+ *
111
+ * @example
112
+ * extractInventorySku('HD6600B-H5490205B-C/P-25KG-PALLET-P001234')
113
+ * // Returns: "HD6600B-H5490205B-C/P-25KG-PALLET"
114
+ */
115
+ declare function extractInventorySku(stockSku: string): string | null;
116
+ /**
117
+ * Validate if a string is a valid Inventory SKU format
118
+ */
119
+ declare function isValidInventorySku(sku: string): boolean;
120
+ /**
121
+ * Validate if a string is a valid Stock SKU format
122
+ */
123
+ declare function isValidStockSku(sku: string): boolean;
124
+ /**
125
+ * Generate a human-readable name from SKU components
126
+ * Format: {grade} {lotNumber} {materialCode} {netWeight}kg {packageType}
127
+ *
128
+ * @example
129
+ * generateInventoryName({
130
+ * materialCode: 'C/P',
131
+ * grade: 'HD6600B',
132
+ * lotNumber: 'H5490205B',
133
+ * netWeight: 25.0,
134
+ * packageType: 'PALLET'
135
+ * })
136
+ * // Returns: "HD6600B H5490205B C/P 25kg Pallet"
137
+ */
138
+ declare function generateInventoryName(params: InventorySkuParams): string;
139
+
140
+ export { type InventorySkuParams, type StockSkuParams, extractInventorySku, formatWeight, generateInventoryName, generateInventorySku, generateStockSku, isValidInventorySku, isValidStockSku, normalizeSkuComponent, parseInventorySku, parseStockSku };
package/dist/index.js ADDED
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ extractInventorySku: () => extractInventorySku,
24
+ formatWeight: () => formatWeight,
25
+ generateInventoryName: () => generateInventoryName,
26
+ generateInventorySku: () => generateInventorySku,
27
+ generateStockSku: () => generateStockSku,
28
+ isValidInventorySku: () => isValidInventorySku,
29
+ isValidStockSku: () => isValidStockSku,
30
+ normalizeSkuComponent: () => normalizeSkuComponent,
31
+ parseInventorySku: () => parseInventorySku,
32
+ parseStockSku: () => parseStockSku
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+ function normalizeSkuComponent(component) {
36
+ return component.trim().toUpperCase().replace(/\s+/g, "_").replace(/[^A-Z0-9/_]/g, "").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
37
+ }
38
+ function formatWeight(weight) {
39
+ if (Number.isInteger(weight)) {
40
+ return weight.toString();
41
+ }
42
+ return weight.toFixed(2).replace(/\.?0+$/, "");
43
+ }
44
+ function generateInventorySku(params) {
45
+ const { materialCode, grade, lotNumber, netWeight, packageType } = params;
46
+ const normalizedMaterialCode = normalizeSkuComponent(materialCode);
47
+ const normalizedGrade = normalizeSkuComponent(grade);
48
+ const normalizedLotNumber = normalizeSkuComponent(lotNumber);
49
+ const normalizedPackageType = normalizeSkuComponent(packageType);
50
+ const weightStr = formatWeight(netWeight);
51
+ return `${normalizedGrade}-${normalizedLotNumber}-${normalizedMaterialCode}-${weightStr}KG-${normalizedPackageType}`;
52
+ }
53
+ function generateStockSku(params) {
54
+ const inventorySku = generateInventorySku(params);
55
+ const normalizedStockNumber = normalizeSkuComponent(params.stockNumber);
56
+ return `${inventorySku}-${normalizedStockNumber}`;
57
+ }
58
+ function parseInventorySku(sku) {
59
+ const parts = sku.split("-");
60
+ if (parts.length < 5) {
61
+ return null;
62
+ }
63
+ const grade = parts[0];
64
+ const lotNumber = parts[1];
65
+ const materialCode = parts[2];
66
+ const weightPart = parts[3];
67
+ if (!weightPart.endsWith("KG")) {
68
+ return null;
69
+ }
70
+ const netWeight = parseFloat(weightPart.replace("KG", ""));
71
+ const packageType = parts[4];
72
+ return {
73
+ materialCode,
74
+ grade,
75
+ lotNumber,
76
+ netWeight,
77
+ packageType
78
+ };
79
+ }
80
+ function parseStockSku(sku) {
81
+ const parts = sku.split("-");
82
+ if (parts.length < 6) {
83
+ return null;
84
+ }
85
+ const inventoryParams = parseInventorySku(parts.slice(0, 5).join("-"));
86
+ if (!inventoryParams) {
87
+ return null;
88
+ }
89
+ return {
90
+ ...inventoryParams,
91
+ stockNumber: parts[5]
92
+ };
93
+ }
94
+ function extractInventorySku(stockSku) {
95
+ const parsed = parseStockSku(stockSku);
96
+ if (!parsed) {
97
+ return null;
98
+ }
99
+ return generateInventorySku(parsed);
100
+ }
101
+ function isValidInventorySku(sku) {
102
+ return parseInventorySku(sku) !== null;
103
+ }
104
+ function isValidStockSku(sku) {
105
+ return parseStockSku(sku) !== null;
106
+ }
107
+ function generateInventoryName(params) {
108
+ const { materialCode, grade, lotNumber, netWeight, packageType } = params;
109
+ const capitalizedPackageType = packageType.toLowerCase().split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
110
+ return `${grade} ${lotNumber} ${materialCode} ${netWeight}kg ${capitalizedPackageType}`;
111
+ }
112
+ // Annotate the CommonJS export names for ESM import in node:
113
+ 0 && (module.exports = {
114
+ extractInventorySku,
115
+ formatWeight,
116
+ generateInventoryName,
117
+ generateInventorySku,
118
+ generateStockSku,
119
+ isValidInventorySku,
120
+ isValidStockSku,
121
+ normalizeSkuComponent,
122
+ parseInventorySku,
123
+ parseStockSku
124
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,90 @@
1
+ // src/index.ts
2
+ function normalizeSkuComponent(component) {
3
+ return component.trim().toUpperCase().replace(/\s+/g, "_").replace(/[^A-Z0-9/_]/g, "").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
4
+ }
5
+ function formatWeight(weight) {
6
+ if (Number.isInteger(weight)) {
7
+ return weight.toString();
8
+ }
9
+ return weight.toFixed(2).replace(/\.?0+$/, "");
10
+ }
11
+ function generateInventorySku(params) {
12
+ const { materialCode, grade, lotNumber, netWeight, packageType } = params;
13
+ const normalizedMaterialCode = normalizeSkuComponent(materialCode);
14
+ const normalizedGrade = normalizeSkuComponent(grade);
15
+ const normalizedLotNumber = normalizeSkuComponent(lotNumber);
16
+ const normalizedPackageType = normalizeSkuComponent(packageType);
17
+ const weightStr = formatWeight(netWeight);
18
+ return `${normalizedGrade}-${normalizedLotNumber}-${normalizedMaterialCode}-${weightStr}KG-${normalizedPackageType}`;
19
+ }
20
+ function generateStockSku(params) {
21
+ const inventorySku = generateInventorySku(params);
22
+ const normalizedStockNumber = normalizeSkuComponent(params.stockNumber);
23
+ return `${inventorySku}-${normalizedStockNumber}`;
24
+ }
25
+ function parseInventorySku(sku) {
26
+ const parts = sku.split("-");
27
+ if (parts.length < 5) {
28
+ return null;
29
+ }
30
+ const grade = parts[0];
31
+ const lotNumber = parts[1];
32
+ const materialCode = parts[2];
33
+ const weightPart = parts[3];
34
+ if (!weightPart.endsWith("KG")) {
35
+ return null;
36
+ }
37
+ const netWeight = parseFloat(weightPart.replace("KG", ""));
38
+ const packageType = parts[4];
39
+ return {
40
+ materialCode,
41
+ grade,
42
+ lotNumber,
43
+ netWeight,
44
+ packageType
45
+ };
46
+ }
47
+ function parseStockSku(sku) {
48
+ const parts = sku.split("-");
49
+ if (parts.length < 6) {
50
+ return null;
51
+ }
52
+ const inventoryParams = parseInventorySku(parts.slice(0, 5).join("-"));
53
+ if (!inventoryParams) {
54
+ return null;
55
+ }
56
+ return {
57
+ ...inventoryParams,
58
+ stockNumber: parts[5]
59
+ };
60
+ }
61
+ function extractInventorySku(stockSku) {
62
+ const parsed = parseStockSku(stockSku);
63
+ if (!parsed) {
64
+ return null;
65
+ }
66
+ return generateInventorySku(parsed);
67
+ }
68
+ function isValidInventorySku(sku) {
69
+ return parseInventorySku(sku) !== null;
70
+ }
71
+ function isValidStockSku(sku) {
72
+ return parseStockSku(sku) !== null;
73
+ }
74
+ function generateInventoryName(params) {
75
+ const { materialCode, grade, lotNumber, netWeight, packageType } = params;
76
+ const capitalizedPackageType = packageType.toLowerCase().split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
77
+ return `${grade} ${lotNumber} ${materialCode} ${netWeight}kg ${capitalizedPackageType}`;
78
+ }
79
+ export {
80
+ extractInventorySku,
81
+ formatWeight,
82
+ generateInventoryName,
83
+ generateInventorySku,
84
+ generateStockSku,
85
+ isValidInventorySku,
86
+ isValidStockSku,
87
+ normalizeSkuComponent,
88
+ parseInventorySku,
89
+ parseStockSku
90
+ };
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@tewtawanc/loops-utils",
3
+ "version": "1.0.0",
4
+ "description": "Shared utilities for Loops warehouse management system",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format cjs,esm --dts",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "sku",
24
+ "inventory",
25
+ "warehouse"
26
+ ],
27
+ "author": "tewtawanc",
28
+ "license": "MIT",
29
+ "devDependencies": {
30
+ "tsup": "^8.0.0",
31
+ "typescript": "^5.0.0"
32
+ }
33
+ }