@playq/core 0.2.77
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/README.md +41 -0
- package/bin/playq.js +175 -0
- package/cucumber.js +10 -0
- package/dist/exec/featureFileCache.d.ts +21 -0
- package/dist/exec/featureFileCache.js +124 -0
- package/dist/exec/featureFilePreProcess.d.ts +12 -0
- package/dist/exec/featureFilePreProcess.js +208 -0
- package/dist/exec/preLoader.d.ts +1 -0
- package/dist/exec/preLoader.js +72 -0
- package/dist/exec/preProcessEntry.d.ts +1 -0
- package/dist/exec/preProcessEntry.js +83 -0
- package/dist/exec/preProcess_old_todelete.d.ts +1 -0
- package/dist/exec/preProcess_old_todelete.js +258 -0
- package/dist/exec/runner.d.ts +1 -0
- package/dist/exec/runner.js +221 -0
- package/dist/exec/runner_orchestrator.d.ts +1 -0
- package/dist/exec/runner_orchestrator.js +85 -0
- package/dist/exec/sgGenerator.d.ts +11 -0
- package/dist/exec/sgGenerator.js +310 -0
- package/dist/global.d.ts +15 -0
- package/dist/global.js +185 -0
- package/dist/helper/actions/api/apiRequestActions.d.ts +117 -0
- package/dist/helper/actions/api/apiRequestActions.js +374 -0
- package/dist/helper/actions/api/apiValidationActions.d.ts +119 -0
- package/dist/helper/actions/api/apiValidationActions.js +615 -0
- package/dist/helper/actions/apiActions.d.ts +18 -0
- package/dist/helper/actions/apiActions.js +34 -0
- package/dist/helper/actions/apiStepDefs.d.ts +1 -0
- package/dist/helper/actions/apiStepDefs.js +64 -0
- package/dist/helper/actions/comm/commonActions.d.ts +58 -0
- package/dist/helper/actions/comm/commonActions.js +198 -0
- package/dist/helper/actions/comm/utilityActions.d.ts +131 -0
- package/dist/helper/actions/comm/utilityActions.js +351 -0
- package/dist/helper/actions/commActions.d.ts +18 -0
- package/dist/helper/actions/commActions.js +34 -0
- package/dist/helper/actions/commStepDefs.d.ts +1 -0
- package/dist/helper/actions/commStepDefs.js +57 -0
- package/dist/helper/actions/stepGroupStepDefs.d.ts +1 -0
- package/dist/helper/actions/stepGroupStepDefs.js +15 -0
- package/dist/helper/actions/web/alertActions.d.ts +61 -0
- package/dist/helper/actions/web/alertActions.js +224 -0
- package/dist/helper/actions/web/cookieActions.d.ts +45 -0
- package/dist/helper/actions/web/cookieActions.js +186 -0
- package/dist/helper/actions/web/downloadActions.d.ts +40 -0
- package/dist/helper/actions/web/downloadActions.js +153 -0
- package/dist/helper/actions/web/elementReaderActions.d.ts +95 -0
- package/dist/helper/actions/web/elementReaderActions.js +326 -0
- package/dist/helper/actions/web/formActions.d.ts +122 -0
- package/dist/helper/actions/web/formActions.js +423 -0
- package/dist/helper/actions/web/iframeActions.d.ts +23 -0
- package/dist/helper/actions/web/iframeActions.js +108 -0
- package/dist/helper/actions/web/javascriptActions.d.ts +14 -0
- package/dist/helper/actions/web/javascriptActions.js +77 -0
- package/dist/helper/actions/web/keyboardActions.d.ts +35 -0
- package/dist/helper/actions/web/keyboardActions.js +118 -0
- package/dist/helper/actions/web/localStorageActions.d.ts +51 -0
- package/dist/helper/actions/web/localStorageActions.js +163 -0
- package/dist/helper/actions/web/mouseActions.d.ts +240 -0
- package/dist/helper/actions/web/mouseActions.js +609 -0
- package/dist/helper/actions/web/reportingActions.d.ts +34 -0
- package/dist/helper/actions/web/reportingActions.js +58 -0
- package/dist/helper/actions/web/screenshotActions.d.ts +34 -0
- package/dist/helper/actions/web/screenshotActions.js +151 -0
- package/dist/helper/actions/web/testDataActions.d.ts +21 -0
- package/dist/helper/actions/web/testDataActions.js +211 -0
- package/dist/helper/actions/web/validationActions.d.ts +547 -0
- package/dist/helper/actions/web/validationActions.js +1754 -0
- package/dist/helper/actions/web/waitActions.d.ts +191 -0
- package/dist/helper/actions/web/waitActions.js +589 -0
- package/dist/helper/actions/web/webNavigation.d.ts +104 -0
- package/dist/helper/actions/web/webNavigation.js +288 -0
- package/dist/helper/actions/webActions.d.ts +32 -0
- package/dist/helper/actions/webActions.js +48 -0
- package/dist/helper/actions/webStepDefs.d.ts +1 -0
- package/dist/helper/actions/webStepDefs.js +455 -0
- package/dist/helper/browsers/browserManager.d.ts +1 -0
- package/dist/helper/browsers/browserManager.js +56 -0
- package/dist/helper/bundle/defaultEntries.d.ts +6 -0
- package/dist/helper/bundle/defaultEntries.js +200 -0
- package/dist/helper/bundle/env.d.ts +1 -0
- package/dist/helper/bundle/env.js +157 -0
- package/dist/helper/bundle/vars.d.ts +9 -0
- package/dist/helper/bundle/vars.js +375 -0
- package/dist/helper/faker/customFaker.d.ts +55 -0
- package/dist/helper/faker/customFaker.js +45 -0
- package/dist/helper/faker/modules/data/postcodes_valid_sg.json +17 -0
- package/dist/helper/faker/modules/dateTime.d.ts +18 -0
- package/dist/helper/faker/modules/dateTime.js +106 -0
- package/dist/helper/faker/modules/mobile.d.ts +4 -0
- package/dist/helper/faker/modules/mobile.js +59 -0
- package/dist/helper/faker/modules/nric.d.ts +32 -0
- package/dist/helper/faker/modules/nric.js +84 -0
- package/dist/helper/faker/modules/passport.d.ts +3 -0
- package/dist/helper/faker/modules/passport.js +36 -0
- package/dist/helper/faker/modules/person.d.ts +14 -0
- package/dist/helper/faker/modules/person.js +73 -0
- package/dist/helper/faker/modules/postcode.d.ts +6 -0
- package/dist/helper/faker/modules/postcode.js +47 -0
- package/dist/helper/fixtures/locAggregate.d.ts +7 -0
- package/dist/helper/fixtures/locAggregate.js +94 -0
- package/dist/helper/fixtures/logFixture.d.ts +8 -0
- package/dist/helper/fixtures/logFixture.js +56 -0
- package/dist/helper/fixtures/webFixture.d.ts +19 -0
- package/dist/helper/fixtures/webFixture.js +186 -0
- package/dist/helper/fixtures/webLocFixture.d.ts +2 -0
- package/dist/helper/fixtures/webLocFixture.js +144 -0
- package/dist/helper/report/allureStepLogger.d.ts +0 -0
- package/dist/helper/report/allureStepLogger.js +25 -0
- package/dist/helper/report/customiseReport.d.ts +1 -0
- package/dist/helper/report/customiseReport.js +55 -0
- package/dist/helper/report/init.d.ts +1 -0
- package/dist/helper/report/init.js +14 -0
- package/dist/helper/report/report.d.ts +1 -0
- package/dist/helper/report/report.js +102 -0
- package/dist/helper/util/dataLoader.d.ts +10 -0
- package/dist/helper/util/dataLoader.js +73 -0
- package/dist/helper/util/logger.d.ts +4 -0
- package/dist/helper/util/logger.js +61 -0
- package/dist/helper/util/session/sessionUtil.d.ts +26 -0
- package/dist/helper/util/session/sessionUtil.js +729 -0
- package/dist/helper/util/stepHelpers.d.ts +2 -0
- package/dist/helper/util/stepHelpers.js +16 -0
- package/dist/helper/util/test-data/dataLoader.d.ts +7 -0
- package/dist/helper/util/test-data/dataLoader.js +145 -0
- package/dist/helper/util/test-data/dataTest.d.ts +10 -0
- package/dist/helper/util/test-data/dataTest.js +216 -0
- package/dist/helper/util/totp/totpHelper.d.ts +38 -0
- package/dist/helper/util/totp/totpHelper.js +117 -0
- package/dist/helper/util/utilities/cryptoUtil.d.ts +2 -0
- package/dist/helper/util/utilities/cryptoUtil.js +53 -0
- package/dist/helper/util/utilities/schemaGeneratorUtil.d.ts +2 -0
- package/dist/helper/util/utilities/schemaGeneratorUtil.js +129 -0
- package/dist/helper/util/utils.d.ts +2 -0
- package/dist/helper/util/utils.js +22 -0
- package/dist/helper/wrapper/PlaywrightWrappers.d.ts +8 -0
- package/dist/helper/wrapper/PlaywrightWrappers.js +26 -0
- package/dist/helper/wrapper/assert.d.ts +9 -0
- package/dist/helper/wrapper/assert.js +23 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +57 -0
- package/dist/scripts/get-versions.d.ts +1 -0
- package/dist/scripts/get-versions.js +98 -0
- package/dist/scripts/posttest.d.ts +1 -0
- package/dist/scripts/posttest.js +29 -0
- package/dist/scripts/pretest.d.ts +1 -0
- package/dist/scripts/pretest.js +57 -0
- package/dist/scripts/util.d.ts +1 -0
- package/dist/scripts/util.js +376 -0
- package/package.json +68 -0
- package/src/exec/featureFileCache.ts +80 -0
- package/src/exec/featureFilePreProcess.ts +239 -0
- package/src/exec/preLoader.ts +72 -0
- package/src/exec/preProcessEntry.ts +59 -0
- package/src/exec/preProcess_old_todelete.ts +289 -0
- package/src/exec/runner.ts +241 -0
- package/src/exec/runnerCuke.js +90 -0
- package/src/exec/runner_orchestrator.ts +91 -0
- package/src/exec/sgGenerator.ts +373 -0
- package/src/global.ts +130 -0
- package/src/helper/actions/api/apiRequestActions.ts +362 -0
- package/src/helper/actions/api/apiValidationActions.ts +594 -0
- package/src/helper/actions/apiActions.ts +18 -0
- package/src/helper/actions/apiStepDefs.ts +80 -0
- package/src/helper/actions/comm/commonActions.ts +165 -0
- package/src/helper/actions/comm/utilityActions.ts +344 -0
- package/src/helper/actions/commActions.ts +18 -0
- package/src/helper/actions/commStepDefs.ts +72 -0
- package/src/helper/actions/stepGroupStepDefs.ts +17 -0
- package/src/helper/actions/web/alertActions.ts +179 -0
- package/src/helper/actions/web/cookieActions.ts +124 -0
- package/src/helper/actions/web/downloadActions.ts +129 -0
- package/src/helper/actions/web/elementReaderActions.ts +323 -0
- package/src/helper/actions/web/formActions.ts +469 -0
- package/src/helper/actions/web/iframeActions.ts +67 -0
- package/src/helper/actions/web/javascriptActions.ts +38 -0
- package/src/helper/actions/web/keyboardActions.ts +101 -0
- package/src/helper/actions/web/localStorageActions.ts +109 -0
- package/src/helper/actions/web/mouseActions.ts +864 -0
- package/src/helper/actions/web/reportingActions.ts +53 -0
- package/src/helper/actions/web/screenshotActions.ts +124 -0
- package/src/helper/actions/web/testDataActions.ts +162 -0
- package/src/helper/actions/web/validationActions.ts +2287 -0
- package/src/helper/actions/web/waitActions.ts +757 -0
- package/src/helper/actions/web/webNavigation.ts +313 -0
- package/src/helper/actions/webActions.ts +33 -0
- package/src/helper/actions/webStepDefs.ts +505 -0
- package/src/helper/browsers/browserManager.ts +23 -0
- package/src/helper/bundle/defaultEntries.ts +208 -0
- package/src/helper/bundle/env.ts +119 -0
- package/src/helper/bundle/vars.ts +368 -0
- package/src/helper/faker/customFaker.ts +107 -0
- package/src/helper/faker/modules/data/postcodes_valid_sg.json +17 -0
- package/src/helper/faker/modules/dateTime.ts +121 -0
- package/src/helper/faker/modules/mobile.ts +58 -0
- package/src/helper/faker/modules/nric.ts +109 -0
- package/src/helper/faker/modules/passport.ts +34 -0
- package/src/helper/faker/modules/person.ts +93 -0
- package/src/helper/faker/modules/postcode.ts +57 -0
- package/src/helper/fixtures/locAggregate.ts +61 -0
- package/src/helper/fixtures/logFixture.ts +57 -0
- package/src/helper/fixtures/webFixture.ts +206 -0
- package/src/helper/fixtures/webLocFixture.ts +143 -0
- package/src/helper/report/allureStepLogger.ts +26 -0
- package/src/helper/report/customiseReport.ts +61 -0
- package/src/helper/report/init.ts +18 -0
- package/src/helper/report/report.ts +72 -0
- package/src/helper/util/dataLoader.ts +42 -0
- package/src/helper/util/logger.ts +32 -0
- package/src/helper/util/session/sessionUtil.ts +839 -0
- package/src/helper/util/stepHelpers.ts +14 -0
- package/src/helper/util/test-data/dataLoader.ts +108 -0
- package/src/helper/util/test-data/dataTest.ts +191 -0
- package/src/helper/util/test-data/registerUser.json +7 -0
- package/src/helper/util/totp/totpHelper.ts +102 -0
- package/src/helper/util/utilities/cryptoUtil.ts +53 -0
- package/src/helper/util/utilities/schemaGeneratorUtil.ts +143 -0
- package/src/helper/util/utils.ts +28 -0
- package/src/helper/wrapper/PlaywrightWrappers.ts +28 -0
- package/src/helper/wrapper/assert.ts +25 -0
- package/src/index.ts +17 -0
- package/src/scripts/get-versions.ts +68 -0
- package/src/scripts/posttest.ts +32 -0
- package/src/scripts/pretest.ts +48 -0
- package/src/scripts/util.ts +406 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.attachResolvedStep = attachResolvedStep;
|
|
4
|
+
exports.defineLoggedStep = defineLoggedStep;
|
|
5
|
+
const global_1 = require("../../global");
|
|
6
|
+
async function attachResolvedStep(thisArg, template) {
|
|
7
|
+
const resolved = global_1.vars.replaceVariables(template);
|
|
8
|
+
await thisArg.attach(`🧾 Resolved Step: ${resolved}`, 'text/plain');
|
|
9
|
+
}
|
|
10
|
+
function defineLoggedStep(pattern, implementation) {
|
|
11
|
+
return function (...args) {
|
|
12
|
+
const stepText = pattern.replace(/\{param\}/g, (_match, i) => `"${args[i]}"`);
|
|
13
|
+
attachResolvedStep.call(this, stepText);
|
|
14
|
+
return implementation.apply(this, args);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads test data from .json, .xlsx, or .csv
|
|
3
|
+
*
|
|
4
|
+
* @param file - Filename WITH extension, e.g., "login.json", "login.xlsx", "login.csv"
|
|
5
|
+
* @param sheetName - (optional) Sheet name for Excel files
|
|
6
|
+
*/
|
|
7
|
+
export declare function getTestData(file: string, sheetName?: string): any[];
|
|
@@ -0,0 +1,145 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getTestData = getTestData;
|
|
40
|
+
const fs_1 = __importDefault(require("fs"));
|
|
41
|
+
const path_1 = __importDefault(require("path"));
|
|
42
|
+
const XLSX = __importStar(require("@e965/xlsx"));
|
|
43
|
+
/**
|
|
44
|
+
* Reads test data from .json, .xlsx, or .csv
|
|
45
|
+
*
|
|
46
|
+
* @param file - Filename WITH extension, e.g., "login.json", "login.xlsx", "login.csv"
|
|
47
|
+
* @param sheetName - (optional) Sheet name for Excel files
|
|
48
|
+
*/
|
|
49
|
+
function getTestData(file, sheetName) {
|
|
50
|
+
// Attempt to locate the project's test-data directory robustly.
|
|
51
|
+
// Strategy:
|
|
52
|
+
// 1. Starting at process.cwd(), walk upward looking for a folder that
|
|
53
|
+
// contains a package.json (project root) and a test-data subfolder.
|
|
54
|
+
// 2. If found, use <foundRoot>/test-data/<file>.
|
|
55
|
+
// 3. Otherwise, fallback to process.cwd()/test-data/<file> and report a clear ENOENT.
|
|
56
|
+
function findProjectRootWithTestData(startDir) {
|
|
57
|
+
let current = path_1.default.resolve(startDir);
|
|
58
|
+
const root = path_1.default.parse(current).root;
|
|
59
|
+
while (true) {
|
|
60
|
+
const pkg = path_1.default.join(current, 'package.json');
|
|
61
|
+
const td = path_1.default.join(current, 'test-data');
|
|
62
|
+
if (fs_1.default.existsSync(pkg) && fs_1.default.existsSync(td) && fs_1.default.statSync(td).isDirectory()) {
|
|
63
|
+
return td;
|
|
64
|
+
}
|
|
65
|
+
if (current === root)
|
|
66
|
+
break;
|
|
67
|
+
current = path_1.default.dirname(current);
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const start = process.cwd();
|
|
72
|
+
const projectTestData = findProjectRootWithTestData(start);
|
|
73
|
+
// If not found by walking upward, also check immediate subdirectories of the
|
|
74
|
+
// current directory. This handles the common developer workspace layout where
|
|
75
|
+
// the workspace root contains multiple project folders (e.g. PlayQ_PROJECT).
|
|
76
|
+
let basePath;
|
|
77
|
+
if (projectTestData) {
|
|
78
|
+
basePath = projectTestData;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// scan one-level children for a project that contains package.json and test-data
|
|
82
|
+
const children = fs_1.default.readdirSync(start, { withFileTypes: true });
|
|
83
|
+
let found = null;
|
|
84
|
+
for (const child of children) {
|
|
85
|
+
if (!child.isDirectory())
|
|
86
|
+
continue;
|
|
87
|
+
const candidate = path_1.default.join(start, child.name);
|
|
88
|
+
const pkg = path_1.default.join(candidate, 'package.json');
|
|
89
|
+
const td = path_1.default.join(candidate, 'test-data');
|
|
90
|
+
try {
|
|
91
|
+
if (fs_1.default.existsSync(pkg) && fs_1.default.existsSync(td) && fs_1.default.statSync(td).isDirectory()) {
|
|
92
|
+
found = td;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
// ignore permission or stat errors on non-readable dirs
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
basePath = found || path_1.default.resolve(process.cwd(), 'test-data');
|
|
101
|
+
}
|
|
102
|
+
const filePath = path_1.default.join(basePath, file);
|
|
103
|
+
if (!fs_1.default.existsSync(filePath)) {
|
|
104
|
+
throw new Error(`ENOENT: test data file not found: ${filePath}. Searched from ${start}`);
|
|
105
|
+
}
|
|
106
|
+
const ext = path_1.default.extname(file).toLowerCase();
|
|
107
|
+
switch (ext) {
|
|
108
|
+
case '.json': {
|
|
109
|
+
const raw = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
110
|
+
return JSON.parse(raw);
|
|
111
|
+
}
|
|
112
|
+
case '.xlsx': {
|
|
113
|
+
const workbook = XLSX.readFile(filePath);
|
|
114
|
+
const sheet = workbook.Sheets[sheetName || workbook.SheetNames[0]];
|
|
115
|
+
const rows = XLSX.utils.sheet_to_json(sheet, { raw: false });
|
|
116
|
+
// Try to parse booleans/numbers
|
|
117
|
+
return rows.map(row => {
|
|
118
|
+
const parsedRow = {};
|
|
119
|
+
for (const key in row) {
|
|
120
|
+
const value = row[key];
|
|
121
|
+
if (value === 'true' || value === 'false') {
|
|
122
|
+
parsedRow[key] = value === 'true';
|
|
123
|
+
}
|
|
124
|
+
else if (!isNaN(value) && value.trim() !== '') {
|
|
125
|
+
parsedRow[key] = Number(value);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
parsedRow[key] = value;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return parsedRow;
|
|
132
|
+
});
|
|
133
|
+
// const workbook = XLSX.readFile(filePath);
|
|
134
|
+
// const sheet = workbook.Sheets[sheetName || workbook.SheetNames[0]];
|
|
135
|
+
// return XLSX.utils.sheet_to_json(sheet);
|
|
136
|
+
}
|
|
137
|
+
case '.csv': {
|
|
138
|
+
const fileData = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
139
|
+
const worksheet = XLSX.read(fileData, { type: 'string' }).Sheets['Sheet1'];
|
|
140
|
+
return XLSX.utils.sheet_to_json(worksheet);
|
|
141
|
+
}
|
|
142
|
+
default:
|
|
143
|
+
throw new Error(`Unsupported file extension: ${ext}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function dataTest<T extends Record<string, any>>(label: string, dataSource: T[] | {
|
|
2
|
+
file: string;
|
|
3
|
+
filter?: string;
|
|
4
|
+
sheet?: string;
|
|
5
|
+
testType?: string;
|
|
6
|
+
suffix?: string;
|
|
7
|
+
}, callback: (args: {
|
|
8
|
+
row: T;
|
|
9
|
+
page?: any;
|
|
10
|
+
}) => Promise<void>): void;
|
|
@@ -0,0 +1,216 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.dataTest = dataTest;
|
|
37
|
+
// dataTest.ts
|
|
38
|
+
const test_1 = require("@playwright/test");
|
|
39
|
+
const dataLoader_1 = require("./dataLoader");
|
|
40
|
+
const vars = __importStar(require("../../bundle/vars"));
|
|
41
|
+
const customFaker_1 = require("../../faker/customFaker");
|
|
42
|
+
function dataTest(label, dataSource, callback) {
|
|
43
|
+
let dataset = [];
|
|
44
|
+
const { testType = "UI", suffix = "" } = typeof dataSource === "object" && !Array.isArray(dataSource) ? dataSource : {};
|
|
45
|
+
if (Array.isArray(dataSource)) {
|
|
46
|
+
dataset = applyRowReplacements(dataSource);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
let { file, filter, sheet } = dataSource;
|
|
50
|
+
file = vars.replaceVariables(file);
|
|
51
|
+
sheet = (sheet) ? vars.replaceVariables(sheet) : undefined;
|
|
52
|
+
filter = vars.replaceVariables(filter);
|
|
53
|
+
const raw = (0, dataLoader_1.getTestData)(file, sheet);
|
|
54
|
+
// Expand faker/variable placeholders within each row before filtering/scheduling tests
|
|
55
|
+
const preprocessed = applyRowReplacements(raw);
|
|
56
|
+
dataset = filter
|
|
57
|
+
? preprocessed.filter(row => {
|
|
58
|
+
try {
|
|
59
|
+
// Create a scoped function where row keys are destructured
|
|
60
|
+
const fn = new Function("row", `
|
|
61
|
+
const { ${Object.keys(row).join(", ")} } = row;
|
|
62
|
+
return ${filter};
|
|
63
|
+
`);
|
|
64
|
+
return fn(row);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.warn(`⚠️ Filter failed: ${filter}`, err);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
: preprocessed;
|
|
72
|
+
}
|
|
73
|
+
test_1.test.describe(label, () => {
|
|
74
|
+
dataset.forEach((row, index) => {
|
|
75
|
+
vars.setValue('playq.iteration.count', `${index + 1}`);
|
|
76
|
+
const name = `${label} ${vars.replaceVariables(replaceIterationDataVars(suffix, row))} [-${index + 1}-]`;
|
|
77
|
+
if (testType.toUpperCase() === "API") {
|
|
78
|
+
(0, test_1.test)(name, async () => {
|
|
79
|
+
test_1.test.info().annotations.push({ type: "tag", description: label });
|
|
80
|
+
await callback({ row });
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
(0, test_1.test)(name, async ({ page }) => {
|
|
85
|
+
test_1.test.info().annotations.push({ type: "tag", description: label });
|
|
86
|
+
await callback({ row, page });
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// ----------------- helpers -----------------
|
|
93
|
+
function applyRowReplacements(rows) {
|
|
94
|
+
return rows.map((row) => {
|
|
95
|
+
const out = { ...row };
|
|
96
|
+
for (const k of Object.keys(out)) {
|
|
97
|
+
const v = out[k];
|
|
98
|
+
if (typeof v === 'string') {
|
|
99
|
+
// First, evaluate any faker placeholders
|
|
100
|
+
const withFaker = replaceFakerPlaceholders(v);
|
|
101
|
+
// Then, apply generic variable replacements
|
|
102
|
+
out[k] = typeof withFaker === 'string' ? vars.replaceVariables(withFaker) : withFaker;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function replaceFakerPlaceholders(input) {
|
|
109
|
+
const trimmed = input.trim();
|
|
110
|
+
// Entire value is wrapped: #{faker....}
|
|
111
|
+
const wrapped = trimmed.match(/^#\{(faker(?:\.[a-zA-Z0-9_]+)+\((.*)\))\}$/);
|
|
112
|
+
if (wrapped) {
|
|
113
|
+
return evalFakerCall(wrapped[1]);
|
|
114
|
+
}
|
|
115
|
+
// Entire value is a faker call: faker....
|
|
116
|
+
const full = trimmed.match(/^faker((?:\.[a-zA-Z0-9_]+)+)\((.*)\)$/);
|
|
117
|
+
if (full) {
|
|
118
|
+
return evalFakerFromParts(full[1], full[2]);
|
|
119
|
+
}
|
|
120
|
+
// Embedded placeholders inside a larger string
|
|
121
|
+
return input.replace(/#\{faker((?:\.[a-zA-Z0-9_]+)+)\((.*?)\)\}/g, (_m, pathPart, argsRaw) => {
|
|
122
|
+
try {
|
|
123
|
+
const val = evalFakerFromParts(pathPart, argsRaw);
|
|
124
|
+
return String(val);
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
console.warn(`⚠️ Failed to evaluate faker placeholder: #{faker${pathPart}(${argsRaw})}`, e);
|
|
128
|
+
return _m;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function evalFakerCall(expr) {
|
|
133
|
+
// expr like: faker.xxx.yyy(args)
|
|
134
|
+
const m = expr.match(/^faker((?:\.[a-zA-Z0-9_]+)+)\((.*)\)$/);
|
|
135
|
+
if (!m)
|
|
136
|
+
throw new Error(`Invalid faker expression: ${expr}`);
|
|
137
|
+
return evalFakerFromParts(m[1], m[2]);
|
|
138
|
+
}
|
|
139
|
+
function evalFakerFromParts(pathPart, argsRaw) {
|
|
140
|
+
const path = pathPart.replace(/^\./, '');
|
|
141
|
+
const parts = path.split('.');
|
|
142
|
+
// Prefer global faker set up by core; fall back to imported one
|
|
143
|
+
let ctx = globalThis.faker || customFaker_1.faker;
|
|
144
|
+
let fn = ctx;
|
|
145
|
+
for (const p of parts) {
|
|
146
|
+
fn = fn === null || fn === void 0 ? void 0 : fn[p];
|
|
147
|
+
}
|
|
148
|
+
if (typeof fn !== 'function')
|
|
149
|
+
throw new Error(`Resolved faker path is not a function: faker.${path}`);
|
|
150
|
+
const args = parseFakerArgs(argsRaw);
|
|
151
|
+
return fn(...args);
|
|
152
|
+
}
|
|
153
|
+
function parseFakerArgs(argsRaw) {
|
|
154
|
+
const trimmed = (argsRaw || '').trim();
|
|
155
|
+
if (!trimmed)
|
|
156
|
+
return [];
|
|
157
|
+
if (trimmed.startsWith('{')) {
|
|
158
|
+
// Object literal; normalize to JSON
|
|
159
|
+
const normalized = trimmed
|
|
160
|
+
.replace(/([{,]\s*)([a-zA-Z0-9_]+)\s*:/g, '$1"$2":')
|
|
161
|
+
.replace(/'/g, '"');
|
|
162
|
+
try {
|
|
163
|
+
return [JSON.parse(normalized)];
|
|
164
|
+
}
|
|
165
|
+
catch (e) {
|
|
166
|
+
throw new Error(`Failed to parse faker argument object: ${argsRaw}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Simple comma-separated values (strip surrounding quotes)
|
|
170
|
+
return splitArgs(trimmed).map(a => a.trim().replace(/^(["'])(.*)\1$/, '$2'));
|
|
171
|
+
}
|
|
172
|
+
function splitArgs(s) {
|
|
173
|
+
const out = [];
|
|
174
|
+
let buf = '';
|
|
175
|
+
let depth = 0;
|
|
176
|
+
let quote = null;
|
|
177
|
+
for (let i = 0; i < s.length; i++) {
|
|
178
|
+
const ch = s[i];
|
|
179
|
+
if (quote) {
|
|
180
|
+
if (ch === quote && s[i - 1] !== '\\') {
|
|
181
|
+
quote = null;
|
|
182
|
+
}
|
|
183
|
+
buf += ch;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (ch === '"' || ch === "'") {
|
|
187
|
+
quote = ch;
|
|
188
|
+
buf += ch;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (ch === '{' || ch === '[' || ch === '(')
|
|
192
|
+
depth++;
|
|
193
|
+
if (ch === '}' || ch === ']' || ch === ')')
|
|
194
|
+
depth--;
|
|
195
|
+
if (ch === ',' && depth === 0) {
|
|
196
|
+
out.push(buf);
|
|
197
|
+
buf = '';
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
buf += ch;
|
|
201
|
+
}
|
|
202
|
+
if (buf)
|
|
203
|
+
out.push(buf);
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Replaces all #{playq.iteration.data.KEY} in the input string with the value from the row object.
|
|
208
|
+
* @param input The string containing placeholders.
|
|
209
|
+
* @param row The row object with data.
|
|
210
|
+
* @returns The string with placeholders replaced.
|
|
211
|
+
*/
|
|
212
|
+
function replaceIterationDataVars(input, row) {
|
|
213
|
+
return input.replace(/#\{playq\.iteration\.data\.([a-zA-Z0-9_]+)\}/g, (_, key) => {
|
|
214
|
+
return row[key] !== undefined ? String(row[key]) : '';
|
|
215
|
+
});
|
|
216
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export declare class TOTPHelper {
|
|
2
|
+
private secret;
|
|
3
|
+
private serviceName;
|
|
4
|
+
private accountName;
|
|
5
|
+
constructor(secret?: string, serviceName?: string, accountName?: string);
|
|
6
|
+
/**
|
|
7
|
+
* Generate a new TOTP secret
|
|
8
|
+
*/
|
|
9
|
+
generateSecret(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Generate current TOTP token
|
|
12
|
+
*/
|
|
13
|
+
generateToken(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Verify TOTP token
|
|
16
|
+
*/
|
|
17
|
+
verifyToken(token: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Get OTP Auth URL for QR code generation
|
|
20
|
+
*/
|
|
21
|
+
getOtpAuthUrl(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Generate QR code for authenticator app setup
|
|
24
|
+
*/
|
|
25
|
+
generateQRCode(): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Get the secret (for environment variable storage)
|
|
28
|
+
*/
|
|
29
|
+
getSecret(): string;
|
|
30
|
+
/**
|
|
31
|
+
* Check if current time is near token expiry
|
|
32
|
+
*/
|
|
33
|
+
getTimeRemaining(): number;
|
|
34
|
+
/**
|
|
35
|
+
* Generate token with retry logic for time window
|
|
36
|
+
*/
|
|
37
|
+
generateTokenWithRetry(maxRetries?: number): Promise<string>;
|
|
38
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TOTPHelper = void 0;
|
|
37
|
+
const otplib_1 = require("otplib");
|
|
38
|
+
const QRCode = __importStar(require("qrcode"));
|
|
39
|
+
class TOTPHelper {
|
|
40
|
+
constructor(secret, serviceName = 'PlayQ', accountName = 'automation') {
|
|
41
|
+
this.secret = secret || this.generateSecret();
|
|
42
|
+
this.serviceName = serviceName;
|
|
43
|
+
this.accountName = accountName;
|
|
44
|
+
// Configure otplib options
|
|
45
|
+
otplib_1.authenticator.options = {
|
|
46
|
+
window: 2, // Allow 2 time steps tolerance
|
|
47
|
+
step: 30 // 30-second time step
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Generate a new TOTP secret
|
|
52
|
+
*/
|
|
53
|
+
generateSecret() {
|
|
54
|
+
return otplib_1.authenticator.generateSecret();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generate current TOTP token
|
|
58
|
+
*/
|
|
59
|
+
generateToken() {
|
|
60
|
+
return otplib_1.authenticator.generate(this.secret);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Verify TOTP token
|
|
64
|
+
*/
|
|
65
|
+
verifyToken(token) {
|
|
66
|
+
return otplib_1.authenticator.verify({
|
|
67
|
+
token,
|
|
68
|
+
secret: this.secret
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get OTP Auth URL for QR code generation
|
|
73
|
+
*/
|
|
74
|
+
getOtpAuthUrl() {
|
|
75
|
+
return otplib_1.authenticator.keyuri(this.accountName, this.serviceName, this.secret);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Generate QR code for authenticator app setup
|
|
79
|
+
*/
|
|
80
|
+
async generateQRCode() {
|
|
81
|
+
const otpAuthUrl = this.getOtpAuthUrl();
|
|
82
|
+
return await QRCode.toDataURL(otpAuthUrl);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get the secret (for environment variable storage)
|
|
86
|
+
*/
|
|
87
|
+
getSecret() {
|
|
88
|
+
return this.secret;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if current time is near token expiry
|
|
92
|
+
*/
|
|
93
|
+
getTimeRemaining() {
|
|
94
|
+
const epoch = Math.round(Date.now() / 1000.0);
|
|
95
|
+
const timeStep = 30;
|
|
96
|
+
return timeStep - (epoch % timeStep);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Generate token with retry logic for time window
|
|
100
|
+
*/
|
|
101
|
+
async generateTokenWithRetry(maxRetries = 3) {
|
|
102
|
+
let attempts = 0;
|
|
103
|
+
while (attempts < maxRetries) {
|
|
104
|
+
const timeRemaining = this.getTimeRemaining();
|
|
105
|
+
// If token expires soon, wait for new window
|
|
106
|
+
if (timeRemaining < 5) {
|
|
107
|
+
console.log(`Token expires in ${timeRemaining}s, waiting for new window...`);
|
|
108
|
+
await new Promise(resolve => setTimeout(resolve, (timeRemaining + 1) * 1000));
|
|
109
|
+
}
|
|
110
|
+
const token = this.generateToken();
|
|
111
|
+
console.log(`Generated TOTP token: ${token.substring(0, 3)}*** (${this.getTimeRemaining()}s remaining)`);
|
|
112
|
+
return token;
|
|
113
|
+
}
|
|
114
|
+
throw new Error('Failed to generate TOTP token after retries');
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.TOTPHelper = TOTPHelper;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.encrypt = encrypt;
|
|
7
|
+
exports.decrypt = decrypt;
|
|
8
|
+
// src/utils/cryptoUtil.ts
|
|
9
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
11
|
+
dotenv_1.default.config();
|
|
12
|
+
const algorithm = 'aes-256-gcm';
|
|
13
|
+
const secretKey = crypto_1.default.scryptSync(process.env.PLAYQ_SECRET_KEY || '_DEFAULT_SECRET_32_CHARACTERS_!_', 'salt', 32);
|
|
14
|
+
const ivLength = 12; // Recommended IV size for GCM
|
|
15
|
+
function encrypt(plaintext) {
|
|
16
|
+
const iv = crypto_1.default.randomBytes(ivLength);
|
|
17
|
+
const cipher = crypto_1.default.createCipheriv(algorithm, secretKey, iv);
|
|
18
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
|
|
19
|
+
const authTag = cipher.getAuthTag();
|
|
20
|
+
const combined = Buffer.concat([iv, authTag, encrypted]);
|
|
21
|
+
return combined.toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
22
|
+
}
|
|
23
|
+
function decrypt(data) {
|
|
24
|
+
const combined = Buffer.from(data.replace(/-/g, '+').replace(/_/g, '/'), 'base64');
|
|
25
|
+
const iv = combined.subarray(0, ivLength);
|
|
26
|
+
const authTag = combined.subarray(ivLength, ivLength + 16);
|
|
27
|
+
const encrypted = combined.subarray(ivLength + 16);
|
|
28
|
+
const decipher = crypto_1.default.createDecipheriv(algorithm, secretKey, iv);
|
|
29
|
+
decipher.setAuthTag(authTag);
|
|
30
|
+
const decrypted = Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
|
31
|
+
return decrypted.toString('utf8');
|
|
32
|
+
}
|
|
33
|
+
// const algorithm = 'aes-256-cbc';
|
|
34
|
+
// const secretKey = process.env.CRYPTO_SECRET_KEY || '_DEFAULT_SECRET_32_CHARACTERS_!_';
|
|
35
|
+
// const ivLength = 16; // AES block size
|
|
36
|
+
// // --- Encrypt ---
|
|
37
|
+
// export function encrypt(text: string): string {
|
|
38
|
+
// const iv = crypto.randomBytes(ivLength);
|
|
39
|
+
// const cipher = crypto.createCipheriv(algorithm, Buffer.from(secretKey, 'utf-8'), iv);
|
|
40
|
+
// let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
41
|
+
// encrypted += cipher.final('hex');
|
|
42
|
+
// return iv.toString('hex') + ':' + encrypted;
|
|
43
|
+
// }
|
|
44
|
+
// // --- Decrypt ---
|
|
45
|
+
// export function decrypt(encryptedText: string): string {
|
|
46
|
+
// const [ivHex, encrypted] = encryptedText.split(':');
|
|
47
|
+
// if (!ivHex || !encrypted) throw new Error('Invalid encrypted text format.');
|
|
48
|
+
// const iv = Buffer.from(ivHex, 'hex');
|
|
49
|
+
// const decipher = crypto.createDecipheriv(algorithm, Buffer.from(secretKey, 'utf-8'), iv);
|
|
50
|
+
// let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
51
|
+
// decrypted += decipher.final('utf8');
|
|
52
|
+
// return decrypted;
|
|
53
|
+
// }
|