@sap-ux/project-integrity 0.3.2 → 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.
- package/dist/fiori-project/index.d.ts +1 -1
- package/dist/fiori-project/index.js +39 -49
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -18
- package/dist/integrity/check.d.ts +1 -1
- package/dist/integrity/check.js +6 -9
- package/dist/integrity/hash.d.ts +1 -1
- package/dist/integrity/hash.js +8 -12
- package/dist/integrity/index.d.ts +1 -1
- package/dist/integrity/index.js +1 -10
- package/dist/integrity/persistence.d.ts +1 -1
- package/dist/integrity/persistence.js +20 -22
- package/dist/integrity/project.d.ts +1 -1
- package/dist/integrity/project.js +28 -36
- package/dist/types.js +1 -2
- package/package.json +7 -3
|
@@ -1,20 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
exports.enableFioriProjectIntegrity = enableFioriProjectIntegrity;
|
|
9
|
-
exports.disableFioriProjectIntegrity = disableFioriProjectIntegrity;
|
|
10
|
-
exports.isFioriProjectIntegrityInitialized = isFioriProjectIntegrityInitialized;
|
|
11
|
-
const node_fs_1 = require("node:fs");
|
|
12
|
-
const node_path_1 = require("node:path");
|
|
13
|
-
const project_access_1 = require("@sap-ux/project-access");
|
|
14
|
-
const integrity_1 = require("../integrity");
|
|
15
|
-
const hash_1 = require("../integrity/hash");
|
|
16
|
-
const persistence_1 = require("../integrity/persistence");
|
|
17
|
-
exports.fioriIntegrityDataPath = (0, node_path_1.join)('.fiori-ai/ai-integrity.json');
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { getCapCustomPaths, getCapModelAndServices } from '@sap-ux/project-access';
|
|
4
|
+
import { checkProjectIntegrity, disableProjectIntegrity, enableProjectIntegrity, initProject, isProjectIntegrityEnabled, updateProjectIntegrity } from '../integrity/index.js';
|
|
5
|
+
import { getContentIntegrity, getFileIntegrity } from '../integrity/hash.js';
|
|
6
|
+
import { readIntegrityData, writeIntegrityData } from '../integrity/persistence.js';
|
|
7
|
+
export const fioriIntegrityDataPath = join('.fiori-ai/ai-integrity.json');
|
|
18
8
|
/**
|
|
19
9
|
* Get the list of files to protect the integrity of.
|
|
20
10
|
*
|
|
@@ -23,15 +13,15 @@ exports.fioriIntegrityDataPath = (0, node_path_1.join)('.fiori-ai/ai-integrity.j
|
|
|
23
13
|
*/
|
|
24
14
|
async function getFileList(projectRoot) {
|
|
25
15
|
const fileList = [];
|
|
26
|
-
const schemaCds =
|
|
27
|
-
if (
|
|
16
|
+
const schemaCds = join(projectRoot, 'db/schema.cds');
|
|
17
|
+
if (existsSync(schemaCds)) {
|
|
28
18
|
fileList.push(schemaCds);
|
|
29
19
|
}
|
|
30
20
|
else {
|
|
31
21
|
throw new Error(`File ${schemaCds} does not exist.`);
|
|
32
22
|
}
|
|
33
|
-
const servicesCds =
|
|
34
|
-
if (
|
|
23
|
+
const servicesCds = join(projectRoot, 'srv/service.cds');
|
|
24
|
+
if (existsSync(servicesCds)) {
|
|
35
25
|
fileList.push(servicesCds);
|
|
36
26
|
}
|
|
37
27
|
else {
|
|
@@ -50,9 +40,9 @@ async function getFileList(projectRoot) {
|
|
|
50
40
|
* including the namespace and structured clone of the definitions.
|
|
51
41
|
*/
|
|
52
42
|
async function getCsnContent(projectRoot) {
|
|
53
|
-
const modelFiles = { srv:
|
|
43
|
+
const modelFiles = { srv: join('srv', 'service.cds'), db: join('db', 'schema.cds') };
|
|
54
44
|
const pathSelection = new Set(Object.keys(modelFiles));
|
|
55
|
-
const result = await
|
|
45
|
+
const result = await getCapModelAndServices({ projectRoot, pathSelection });
|
|
56
46
|
const csn = result.model;
|
|
57
47
|
const data = { namespace: csn.namespace, definitions: structuredClone(csn.definitions) };
|
|
58
48
|
return JSON.stringify(data);
|
|
@@ -65,7 +55,7 @@ async function getCsnContent(projectRoot) {
|
|
|
65
55
|
* @returns - additional content to store in the integrity data
|
|
66
56
|
*/
|
|
67
57
|
async function getAdditionalStringContent(projectRoot) {
|
|
68
|
-
const capCustomPaths = await
|
|
58
|
+
const capCustomPaths = await getCapCustomPaths(projectRoot);
|
|
69
59
|
const cnsContent = await getCsnContent(projectRoot);
|
|
70
60
|
return { capPaths: JSON.stringify(capCustomPaths), csn: cnsContent };
|
|
71
61
|
}
|
|
@@ -74,11 +64,11 @@ async function getAdditionalStringContent(projectRoot) {
|
|
|
74
64
|
*
|
|
75
65
|
* @param projectRoot - root folder of the project
|
|
76
66
|
*/
|
|
77
|
-
async function initFioriProject(projectRoot) {
|
|
78
|
-
const integrityFilePath =
|
|
67
|
+
export async function initFioriProject(projectRoot) {
|
|
68
|
+
const integrityFilePath = join(projectRoot, fioriIntegrityDataPath);
|
|
79
69
|
const fileList = await getFileList(projectRoot);
|
|
80
70
|
const additionalStringContent = await getAdditionalStringContent(projectRoot);
|
|
81
|
-
await
|
|
71
|
+
await initProject({ integrityFilePath, fileList, additionalStringContent });
|
|
82
72
|
}
|
|
83
73
|
/**
|
|
84
74
|
* Check the integrity of a Fiori project.
|
|
@@ -86,11 +76,11 @@ async function initFioriProject(projectRoot) {
|
|
|
86
76
|
* @param projectRoot - root folder of the project
|
|
87
77
|
* @returns - results of the check
|
|
88
78
|
*/
|
|
89
|
-
async function checkFioriProjectIntegrity(projectRoot) {
|
|
90
|
-
const integrityFilePath =
|
|
79
|
+
export async function checkFioriProjectIntegrity(projectRoot) {
|
|
80
|
+
const integrityFilePath = join(projectRoot, fioriIntegrityDataPath);
|
|
91
81
|
const additionalStringContent = await getAdditionalStringContent(projectRoot);
|
|
92
|
-
const checkResult = await
|
|
93
|
-
const integrityData = await
|
|
82
|
+
const checkResult = await checkProjectIntegrity(integrityFilePath, additionalStringContent);
|
|
83
|
+
const integrityData = await readIntegrityData(integrityFilePath);
|
|
94
84
|
/**
|
|
95
85
|
* 1. if csn integrity is the same, but file integrity is different, then is compatible changes (e.g empty spaces, new lines or comments). Add them to equal files, update integrity and remove cds files from different files,
|
|
96
86
|
* 2. if csn integrity is different, but file integrity is same, then CDS compiler might have produced different CSN. Remove csnPath from different content and add it to equal content. Update integrity.
|
|
@@ -103,7 +93,7 @@ async function checkFioriProjectIntegrity(projectRoot) {
|
|
|
103
93
|
checkResult.files.equalFiles.push(...checkResult.files.differentFiles.map((file) => file.filePath));
|
|
104
94
|
// also update integrity.json file
|
|
105
95
|
const cdsDiffFiles = checkResult.files.differentFiles.filter((file) => file.filePath.endsWith('.cds'));
|
|
106
|
-
const diffFileIntegrity = await
|
|
96
|
+
const diffFileIntegrity = await getFileIntegrity(cdsDiffFiles.map((file) => file.filePath));
|
|
107
97
|
const fileIntegrity = integrityData.fileIntegrity.map((file) => {
|
|
108
98
|
const diffFile = diffFileIntegrity.find((diff) => diff.filePath === file.filePath);
|
|
109
99
|
if (diffFile) {
|
|
@@ -111,7 +101,7 @@ async function checkFioriProjectIntegrity(projectRoot) {
|
|
|
111
101
|
}
|
|
112
102
|
return file;
|
|
113
103
|
});
|
|
114
|
-
await
|
|
104
|
+
await writeIntegrityData(integrityFilePath, {
|
|
115
105
|
enabled: integrityData.enabled,
|
|
116
106
|
fileIntegrity,
|
|
117
107
|
contentIntegrity: integrityData.contentIntegrity
|
|
@@ -125,8 +115,8 @@ async function checkFioriProjectIntegrity(projectRoot) {
|
|
|
125
115
|
const [csnContent] = checkResult.additionalStringContent.differentContent.splice(csnIndex, 1);
|
|
126
116
|
checkResult.additionalStringContent.equalContent.push(csnContent.key);
|
|
127
117
|
// update csn content
|
|
128
|
-
const contentIntegrity =
|
|
129
|
-
await
|
|
118
|
+
const contentIntegrity = getContentIntegrity(additionalStringContent);
|
|
119
|
+
await writeIntegrityData(integrityFilePath, {
|
|
130
120
|
enabled: integrityData.enabled,
|
|
131
121
|
fileIntegrity: integrityData.fileIntegrity,
|
|
132
122
|
contentIntegrity
|
|
@@ -140,10 +130,10 @@ async function checkFioriProjectIntegrity(projectRoot) {
|
|
|
140
130
|
*
|
|
141
131
|
* @param projectRoot - root folder of the project
|
|
142
132
|
*/
|
|
143
|
-
async function updateFioriProjectIntegrity(projectRoot) {
|
|
144
|
-
const integrityFilePath =
|
|
133
|
+
export async function updateFioriProjectIntegrity(projectRoot) {
|
|
134
|
+
const integrityFilePath = join(projectRoot, fioriIntegrityDataPath);
|
|
145
135
|
const additionalStringContent = await getAdditionalStringContent(projectRoot);
|
|
146
|
-
await
|
|
136
|
+
await updateProjectIntegrity(integrityFilePath, additionalStringContent);
|
|
147
137
|
}
|
|
148
138
|
/**
|
|
149
139
|
* Return whether integrity is enabled for a Fiori project.
|
|
@@ -151,9 +141,9 @@ async function updateFioriProjectIntegrity(projectRoot) {
|
|
|
151
141
|
* @param projectRoot - root folder of the project
|
|
152
142
|
* @returns true if integrity is enabled, false otherwise
|
|
153
143
|
*/
|
|
154
|
-
async function isFioriProjectIntegrityEnabled(projectRoot) {
|
|
155
|
-
const integrityFilePath =
|
|
156
|
-
return
|
|
144
|
+
export async function isFioriProjectIntegrityEnabled(projectRoot) {
|
|
145
|
+
const integrityFilePath = join(projectRoot, fioriIntegrityDataPath);
|
|
146
|
+
return isProjectIntegrityEnabled(integrityFilePath);
|
|
157
147
|
}
|
|
158
148
|
/**
|
|
159
149
|
* Enable integrity protection for a Fiori project. The Fiori project must be initialized first.
|
|
@@ -161,18 +151,18 @@ async function isFioriProjectIntegrityEnabled(projectRoot) {
|
|
|
161
151
|
*
|
|
162
152
|
* @param projectRoot - root folder of the project
|
|
163
153
|
*/
|
|
164
|
-
async function enableFioriProjectIntegrity(projectRoot) {
|
|
165
|
-
const integrityFilePath =
|
|
166
|
-
await
|
|
154
|
+
export async function enableFioriProjectIntegrity(projectRoot) {
|
|
155
|
+
const integrityFilePath = join(projectRoot, fioriIntegrityDataPath);
|
|
156
|
+
await enableProjectIntegrity(integrityFilePath);
|
|
167
157
|
}
|
|
168
158
|
/**
|
|
169
159
|
* Disable integrity protection for a Fiori project. The Fiori project must be initialized first.
|
|
170
160
|
*
|
|
171
161
|
* @param projectRoot - root folder of the project
|
|
172
162
|
*/
|
|
173
|
-
async function disableFioriProjectIntegrity(projectRoot) {
|
|
174
|
-
const integrityFilePath =
|
|
175
|
-
await
|
|
163
|
+
export async function disableFioriProjectIntegrity(projectRoot) {
|
|
164
|
+
const integrityFilePath = join(projectRoot, fioriIntegrityDataPath);
|
|
165
|
+
await disableProjectIntegrity(integrityFilePath);
|
|
176
166
|
}
|
|
177
167
|
/**
|
|
178
168
|
* Check if the Fiori project integrity is initialized for given root path of a project.
|
|
@@ -181,7 +171,7 @@ async function disableFioriProjectIntegrity(projectRoot) {
|
|
|
181
171
|
* @param projectRoot - root folder of the project
|
|
182
172
|
* @returns - true if the Fiori project integrity is initialized, false otherwise
|
|
183
173
|
*/
|
|
184
|
-
function isFioriProjectIntegrityInitialized(projectRoot) {
|
|
185
|
-
return
|
|
174
|
+
export function isFioriProjectIntegrityInitialized(projectRoot) {
|
|
175
|
+
return existsSync(join(projectRoot, fioriIntegrityDataPath));
|
|
186
176
|
}
|
|
187
177
|
//# sourceMappingURL=index.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { checkProjectIntegrity, disableProjectIntegrity, enableProjectIntegrity, initProject, isProjectIntegrityEnabled, updateProjectIntegrity } from './integrity';
|
|
2
|
-
export { checkFioriProjectIntegrity, disableFioriProjectIntegrity, enableFioriProjectIntegrity, initFioriProject, isFioriProjectIntegrityEnabled, isFioriProjectIntegrityInitialized, updateFioriProjectIntegrity } from './fiori-project';
|
|
1
|
+
export { checkProjectIntegrity, disableProjectIntegrity, enableProjectIntegrity, initProject, isProjectIntegrityEnabled, updateProjectIntegrity } from './integrity/index.js';
|
|
2
|
+
export { checkFioriProjectIntegrity, disableFioriProjectIntegrity, enableFioriProjectIntegrity, initFioriProject, isFioriProjectIntegrityEnabled, isFioriProjectIntegrityInitialized, updateFioriProjectIntegrity } from './fiori-project/index.js';
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.updateFioriProjectIntegrity = exports.isFioriProjectIntegrityInitialized = exports.isFioriProjectIntegrityEnabled = exports.initFioriProject = exports.enableFioriProjectIntegrity = exports.disableFioriProjectIntegrity = exports.checkFioriProjectIntegrity = exports.updateProjectIntegrity = exports.isProjectIntegrityEnabled = exports.initProject = exports.enableProjectIntegrity = exports.disableProjectIntegrity = exports.checkProjectIntegrity = void 0;
|
|
4
|
-
var integrity_1 = require("./integrity");
|
|
5
|
-
Object.defineProperty(exports, "checkProjectIntegrity", { enumerable: true, get: function () { return integrity_1.checkProjectIntegrity; } });
|
|
6
|
-
Object.defineProperty(exports, "disableProjectIntegrity", { enumerable: true, get: function () { return integrity_1.disableProjectIntegrity; } });
|
|
7
|
-
Object.defineProperty(exports, "enableProjectIntegrity", { enumerable: true, get: function () { return integrity_1.enableProjectIntegrity; } });
|
|
8
|
-
Object.defineProperty(exports, "initProject", { enumerable: true, get: function () { return integrity_1.initProject; } });
|
|
9
|
-
Object.defineProperty(exports, "isProjectIntegrityEnabled", { enumerable: true, get: function () { return integrity_1.isProjectIntegrityEnabled; } });
|
|
10
|
-
Object.defineProperty(exports, "updateProjectIntegrity", { enumerable: true, get: function () { return integrity_1.updateProjectIntegrity; } });
|
|
11
|
-
var fiori_project_1 = require("./fiori-project");
|
|
12
|
-
Object.defineProperty(exports, "checkFioriProjectIntegrity", { enumerable: true, get: function () { return fiori_project_1.checkFioriProjectIntegrity; } });
|
|
13
|
-
Object.defineProperty(exports, "disableFioriProjectIntegrity", { enumerable: true, get: function () { return fiori_project_1.disableFioriProjectIntegrity; } });
|
|
14
|
-
Object.defineProperty(exports, "enableFioriProjectIntegrity", { enumerable: true, get: function () { return fiori_project_1.enableFioriProjectIntegrity; } });
|
|
15
|
-
Object.defineProperty(exports, "initFioriProject", { enumerable: true, get: function () { return fiori_project_1.initFioriProject; } });
|
|
16
|
-
Object.defineProperty(exports, "isFioriProjectIntegrityEnabled", { enumerable: true, get: function () { return fiori_project_1.isFioriProjectIntegrityEnabled; } });
|
|
17
|
-
Object.defineProperty(exports, "isFioriProjectIntegrityInitialized", { enumerable: true, get: function () { return fiori_project_1.isFioriProjectIntegrityInitialized; } });
|
|
18
|
-
Object.defineProperty(exports, "updateFioriProjectIntegrity", { enumerable: true, get: function () { return fiori_project_1.updateFioriProjectIntegrity; } });
|
|
1
|
+
export { checkProjectIntegrity, disableProjectIntegrity, enableProjectIntegrity, initProject, isProjectIntegrityEnabled, updateProjectIntegrity } from './integrity/index.js';
|
|
2
|
+
export { checkFioriProjectIntegrity, disableFioriProjectIntegrity, enableFioriProjectIntegrity, initFioriProject, isFioriProjectIntegrityEnabled, isFioriProjectIntegrityInitialized, updateFioriProjectIntegrity } from './fiori-project/index.js';
|
|
19
3
|
//# sourceMappingURL=index.js.map
|
package/dist/integrity/check.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.checkIntegrity = checkIntegrity;
|
|
4
|
-
const node_fs_1 = require("node:fs");
|
|
5
|
-
const hash_1 = require("./hash");
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { getContentIntegrity, getFileIntegrity } from './hash.js';
|
|
6
3
|
/**
|
|
7
4
|
* Check existing integrity data.
|
|
8
5
|
*
|
|
@@ -10,7 +7,7 @@ const hash_1 = require("./hash");
|
|
|
10
7
|
* @param [additionalStringContent] - optional additional new string content
|
|
11
8
|
* @returns - results of the check
|
|
12
9
|
*/
|
|
13
|
-
async function checkIntegrity(integrityData, additionalStringContent) {
|
|
10
|
+
export async function checkIntegrity(integrityData, additionalStringContent) {
|
|
14
11
|
return {
|
|
15
12
|
files: await checkFileIntegrity(integrityData.fileIntegrity),
|
|
16
13
|
additionalStringContent: checkContentIntegrity(integrityData.contentIntegrity, additionalStringContent)
|
|
@@ -27,14 +24,14 @@ async function checkFileIntegrity(fileIntegrity) {
|
|
|
27
24
|
const equalFiles = [];
|
|
28
25
|
const checkFiles = [];
|
|
29
26
|
for (const integrity of fileIntegrity) {
|
|
30
|
-
if (!
|
|
27
|
+
if (!existsSync(integrity.filePath)) {
|
|
31
28
|
differentFiles.push({ filePath: integrity.filePath, oldContent: integrity.content, newContent: '' });
|
|
32
29
|
}
|
|
33
30
|
else {
|
|
34
31
|
checkFiles.push(integrity);
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
|
-
const newFileIntegrityArray = await
|
|
34
|
+
const newFileIntegrityArray = await getFileIntegrity(checkFiles.map((fileIntegrity) => fileIntegrity.filePath));
|
|
38
35
|
for (const newFileIntegrity of newFileIntegrityArray) {
|
|
39
36
|
const oldFileIntegrity = checkFiles.find((fileHash) => fileHash.filePath === newFileIntegrity.filePath);
|
|
40
37
|
if (oldFileIntegrity?.hash === newFileIntegrity.hash) {
|
|
@@ -61,7 +58,7 @@ function checkContentIntegrity(contentIntegrity, additionalStringContent) {
|
|
|
61
58
|
const oldContentIntegrityArray = structuredClone(contentIntegrity);
|
|
62
59
|
const differentContent = [];
|
|
63
60
|
const equalContent = [];
|
|
64
|
-
const newContentIntegrityArray =
|
|
61
|
+
const newContentIntegrityArray = getContentIntegrity(additionalStringContent);
|
|
65
62
|
for (const newContentIntegrity of newContentIntegrityArray) {
|
|
66
63
|
const index = oldContentIntegrityArray.findIndex((content) => content.contentKey === newContentIntegrity.contentKey);
|
|
67
64
|
let foundOldContentIntegrity;
|
package/dist/integrity/hash.d.ts
CHANGED
package/dist/integrity/hash.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.getFileIntegrity = getFileIntegrity;
|
|
4
|
-
exports.getContentIntegrity = getContentIntegrity;
|
|
5
|
-
const node_fs_1 = require("node:fs");
|
|
6
|
-
const node_crypto_1 = require("node:crypto");
|
|
1
|
+
import { createReadStream, existsSync } from 'node:fs';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
7
3
|
/**
|
|
8
4
|
* Create a md5 hash for a given file.
|
|
9
5
|
*
|
|
@@ -13,8 +9,8 @@ const node_crypto_1 = require("node:crypto");
|
|
|
13
9
|
async function computeFileIntegrityData(filePath) {
|
|
14
10
|
return new Promise((resolve, reject) => {
|
|
15
11
|
let content = '';
|
|
16
|
-
const hash =
|
|
17
|
-
const fileStream =
|
|
12
|
+
const hash = createHash('md5');
|
|
13
|
+
const fileStream = createReadStream(filePath);
|
|
18
14
|
fileStream.on('data', (chunk) => {
|
|
19
15
|
content += typeof chunk === 'string' ? chunk : chunk.toString();
|
|
20
16
|
hash.update(typeof chunk === 'string' ? Buffer.from(chunk) : new Uint8Array(chunk));
|
|
@@ -29,8 +25,8 @@ async function computeFileIntegrityData(filePath) {
|
|
|
29
25
|
* @param files - list of files to
|
|
30
26
|
* @returns - promise that resolves to an array of FileHash objects
|
|
31
27
|
*/
|
|
32
|
-
async function getFileIntegrity(files) {
|
|
33
|
-
const nonExistingFiles = files.filter((file) => !
|
|
28
|
+
export async function getFileIntegrity(files) {
|
|
29
|
+
const nonExistingFiles = files.filter((file) => !existsSync(file));
|
|
34
30
|
if (nonExistingFiles.length > 0) {
|
|
35
31
|
throw new Error(`The following files do not exist: ${nonExistingFiles.join(', ')}`);
|
|
36
32
|
}
|
|
@@ -43,14 +39,14 @@ async function getFileIntegrity(files) {
|
|
|
43
39
|
* @param additionalStringContent - key value map of additional content to write as integrity data
|
|
44
40
|
* @returns - array of
|
|
45
41
|
*/
|
|
46
|
-
function getContentIntegrity(additionalStringContent) {
|
|
42
|
+
export function getContentIntegrity(additionalStringContent) {
|
|
47
43
|
const contentIntegrity = [];
|
|
48
44
|
if (additionalStringContent) {
|
|
49
45
|
for (const contentKey in additionalStringContent) {
|
|
50
46
|
const content = additionalStringContent[contentKey];
|
|
51
47
|
contentIntegrity.push({
|
|
52
48
|
contentKey,
|
|
53
|
-
hash:
|
|
49
|
+
hash: createHash('md5').update(content).digest('hex'),
|
|
54
50
|
content
|
|
55
51
|
});
|
|
56
52
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { checkProjectIntegrity, disableProjectIntegrity, enableProjectIntegrity, initProject, isProjectIntegrityEnabled, updateProjectIntegrity } from './project';
|
|
1
|
+
export { checkProjectIntegrity, disableProjectIntegrity, enableProjectIntegrity, initProject, isProjectIntegrityEnabled, updateProjectIntegrity } from './project.js';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/integrity/index.js
CHANGED
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.updateProjectIntegrity = exports.isProjectIntegrityEnabled = exports.initProject = exports.enableProjectIntegrity = exports.disableProjectIntegrity = exports.checkProjectIntegrity = void 0;
|
|
4
|
-
var project_1 = require("./project");
|
|
5
|
-
Object.defineProperty(exports, "checkProjectIntegrity", { enumerable: true, get: function () { return project_1.checkProjectIntegrity; } });
|
|
6
|
-
Object.defineProperty(exports, "disableProjectIntegrity", { enumerable: true, get: function () { return project_1.disableProjectIntegrity; } });
|
|
7
|
-
Object.defineProperty(exports, "enableProjectIntegrity", { enumerable: true, get: function () { return project_1.enableProjectIntegrity; } });
|
|
8
|
-
Object.defineProperty(exports, "initProject", { enumerable: true, get: function () { return project_1.initProject; } });
|
|
9
|
-
Object.defineProperty(exports, "isProjectIntegrityEnabled", { enumerable: true, get: function () { return project_1.isProjectIntegrityEnabled; } });
|
|
10
|
-
Object.defineProperty(exports, "updateProjectIntegrity", { enumerable: true, get: function () { return project_1.updateProjectIntegrity; } });
|
|
1
|
+
export { checkProjectIntegrity, disableProjectIntegrity, enableProjectIntegrity, initProject, isProjectIntegrityEnabled, updateProjectIntegrity } from './project.js';
|
|
11
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const node_path_1 = require("node:path");
|
|
8
|
-
const lz_string_1 = require("lz-string");
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { dirname, join, relative } from 'node:path';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
const _require = createRequire(import.meta.url);
|
|
6
|
+
const { compressToBase64, decompressFromBase64 } = _require('lz-string');
|
|
9
7
|
/**
|
|
10
8
|
* Read hashes from a previously stored hash file.
|
|
11
9
|
* Throws an error if the file does not exist.
|
|
@@ -13,14 +11,14 @@ const lz_string_1 = require("lz-string");
|
|
|
13
11
|
* @param integrityFilePath - path to the integrity file
|
|
14
12
|
* @returns - integrity data
|
|
15
13
|
*/
|
|
16
|
-
async function readIntegrityData(integrityFilePath) {
|
|
17
|
-
if (!
|
|
14
|
+
export async function readIntegrityData(integrityFilePath) {
|
|
15
|
+
if (!existsSync(integrityFilePath)) {
|
|
18
16
|
throw new Error(`Integrity file not found at ${integrityFilePath}`);
|
|
19
17
|
}
|
|
20
|
-
const content = JSON.parse(await
|
|
21
|
-
const integrityDir =
|
|
18
|
+
const content = JSON.parse(await readFile(integrityFilePath, { encoding: 'utf-8' }));
|
|
19
|
+
const integrityDir = dirname(integrityFilePath);
|
|
22
20
|
for (const fileIntegrity of content.fileIntegrity) {
|
|
23
|
-
fileIntegrity.filePath =
|
|
21
|
+
fileIntegrity.filePath = join(integrityDir, fileIntegrity.filePath);
|
|
24
22
|
getifyContent(fileIntegrity);
|
|
25
23
|
}
|
|
26
24
|
for (const contentIntegrity of content.contentIntegrity) {
|
|
@@ -35,24 +33,24 @@ async function readIntegrityData(integrityFilePath) {
|
|
|
35
33
|
* @param integrityFilePath - path to the integrity file
|
|
36
34
|
* @param content - content to write to the integrity file
|
|
37
35
|
*/
|
|
38
|
-
async function writeIntegrityData(integrityFilePath, content) {
|
|
36
|
+
export async function writeIntegrityData(integrityFilePath, content) {
|
|
39
37
|
const clonedContent = structuredClone(content); // clone to ensure integrity data has no getters
|
|
40
|
-
const integrityDir =
|
|
41
|
-
if (!
|
|
42
|
-
await
|
|
38
|
+
const integrityDir = dirname(integrityFilePath);
|
|
39
|
+
if (!existsSync(integrityDir)) {
|
|
40
|
+
await mkdir(integrityDir, { recursive: true });
|
|
43
41
|
}
|
|
44
42
|
for (const fileIntegrity of clonedContent.fileIntegrity) {
|
|
45
|
-
fileIntegrity.filePath =
|
|
43
|
+
fileIntegrity.filePath = relative(integrityDir, fileIntegrity.filePath).replaceAll('\\', '/');
|
|
46
44
|
if (typeof fileIntegrity.content === 'string') {
|
|
47
|
-
fileIntegrity.content =
|
|
45
|
+
fileIntegrity.content = compressToBase64(fileIntegrity.content);
|
|
48
46
|
}
|
|
49
47
|
}
|
|
50
48
|
for (const contentIntegrity of clonedContent.contentIntegrity) {
|
|
51
49
|
if (typeof contentIntegrity.content === 'string') {
|
|
52
|
-
contentIntegrity.content =
|
|
50
|
+
contentIntegrity.content = compressToBase64(contentIntegrity.content);
|
|
53
51
|
}
|
|
54
52
|
}
|
|
55
|
-
await
|
|
53
|
+
await writeFile(integrityFilePath, JSON.stringify(clonedContent), { encoding: 'utf-8' });
|
|
56
54
|
}
|
|
57
55
|
/**
|
|
58
56
|
* Wrap content with getter to decompress on first access. Do nothing if the content does not exist.
|
|
@@ -66,7 +64,7 @@ function getifyContent(integrityObject) {
|
|
|
66
64
|
Object.defineProperty(integrityObject, 'content', {
|
|
67
65
|
get: () => {
|
|
68
66
|
if (!content) {
|
|
69
|
-
content =
|
|
67
|
+
content = decompressFromBase64(compressedContent);
|
|
70
68
|
}
|
|
71
69
|
return content;
|
|
72
70
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CheckIntegrityResult, Content, ProjectSettings } from '../types';
|
|
1
|
+
import type { CheckIntegrityResult, Content, ProjectSettings } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Initialize a project by creating hashes for all selected files in the project. There is an option to add
|
|
4
4
|
* additional key->string content to the integrity data.
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.updateProjectIntegrity = updateProjectIntegrity;
|
|
6
|
-
exports.isProjectIntegrityEnabled = isProjectIntegrityEnabled;
|
|
7
|
-
exports.enableProjectIntegrity = enableProjectIntegrity;
|
|
8
|
-
exports.disableProjectIntegrity = disableProjectIntegrity;
|
|
9
|
-
const node_fs_1 = require("node:fs");
|
|
10
|
-
const hash_1 = require("./hash");
|
|
11
|
-
const persistence_1 = require("./persistence");
|
|
12
|
-
const check_1 = require("./check");
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { getContentIntegrity, getFileIntegrity } from './hash.js';
|
|
3
|
+
import { readIntegrityData, writeIntegrityData } from './persistence.js';
|
|
4
|
+
import { checkIntegrity } from './check.js';
|
|
13
5
|
/**
|
|
14
6
|
* Function to ensure correct sorting of strings.
|
|
15
7
|
*
|
|
@@ -27,11 +19,11 @@ const sortLocal = (a, b) => a.localeCompare(b);
|
|
|
27
19
|
* @param settings.fileList - list of file paths for files to create integrity data for
|
|
28
20
|
* @param [settings.additionalStringContent] - optional key/string map to add to integrity data
|
|
29
21
|
*/
|
|
30
|
-
async function initProject(settings) {
|
|
22
|
+
export async function initProject(settings) {
|
|
31
23
|
const enabled = true;
|
|
32
|
-
const fileIntegrity = await
|
|
33
|
-
const contentIntegrity =
|
|
34
|
-
await
|
|
24
|
+
const fileIntegrity = await getFileIntegrity(settings.fileList);
|
|
25
|
+
const contentIntegrity = getContentIntegrity(settings.additionalStringContent);
|
|
26
|
+
await writeIntegrityData(settings.integrityFilePath, { enabled, fileIntegrity, contentIntegrity });
|
|
35
27
|
}
|
|
36
28
|
/**
|
|
37
29
|
* Check the integrity of a project by comparing the stored integrity data with the current state
|
|
@@ -42,12 +34,12 @@ async function initProject(settings) {
|
|
|
42
34
|
* @param [additionalStringContent] - optional key/string map to add to integrity data
|
|
43
35
|
* @returns - results of the check
|
|
44
36
|
*/
|
|
45
|
-
async function checkProjectIntegrity(integrityFilePath, additionalStringContent) {
|
|
46
|
-
const integrityData = await
|
|
37
|
+
export async function checkProjectIntegrity(integrityFilePath, additionalStringContent) {
|
|
38
|
+
const integrityData = await readIntegrityData(integrityFilePath);
|
|
47
39
|
if (!integrityData.enabled) {
|
|
48
40
|
throw new Error(`Integrity is disabled for the project with integrity data ${integrityFilePath}`);
|
|
49
41
|
}
|
|
50
|
-
const checkResult =
|
|
42
|
+
const checkResult = checkIntegrity(integrityData, additionalStringContent);
|
|
51
43
|
return checkResult;
|
|
52
44
|
}
|
|
53
45
|
/**
|
|
@@ -57,11 +49,11 @@ async function checkProjectIntegrity(integrityFilePath, additionalStringContent)
|
|
|
57
49
|
* @param integrityFilePath - path to file where integrity data is stored
|
|
58
50
|
* @param additionalStringContent - optional key/string map to add to integrity data
|
|
59
51
|
*/
|
|
60
|
-
async function updateProjectIntegrity(integrityFilePath, additionalStringContent) {
|
|
61
|
-
if (!
|
|
52
|
+
export async function updateProjectIntegrity(integrityFilePath, additionalStringContent) {
|
|
53
|
+
if (!existsSync(integrityFilePath)) {
|
|
62
54
|
throw new Error(`Integrity data not found at ${integrityFilePath}`);
|
|
63
55
|
}
|
|
64
|
-
const integrityData = await
|
|
56
|
+
const integrityData = await readIntegrityData(integrityFilePath);
|
|
65
57
|
if (!integrityData.enabled) {
|
|
66
58
|
throw new Error(`Integrity is disabled for the project with integrity data ${integrityFilePath}`);
|
|
67
59
|
}
|
|
@@ -73,9 +65,9 @@ async function updateProjectIntegrity(integrityFilePath, additionalStringContent
|
|
|
73
65
|
Stored content keys: ${existingContentKeys.join(', ')}
|
|
74
66
|
New content keys: ${newContentKeys.join(', ')}`);
|
|
75
67
|
}
|
|
76
|
-
const fileIntegrity = await
|
|
77
|
-
const contentIntegrity =
|
|
78
|
-
await
|
|
68
|
+
const fileIntegrity = await getFileIntegrity(integrityData.fileIntegrity.map((file) => file.filePath));
|
|
69
|
+
const contentIntegrity = getContentIntegrity(additionalStringContent);
|
|
70
|
+
await writeIntegrityData(integrityFilePath, { enabled: integrityData.enabled, fileIntegrity, contentIntegrity });
|
|
79
71
|
}
|
|
80
72
|
/**
|
|
81
73
|
* Return whether integrity is enabled for a project.
|
|
@@ -83,11 +75,11 @@ New content keys: ${newContentKeys.join(', ')}`);
|
|
|
83
75
|
* @param integrityFilePath - path to file where integrity data is stored
|
|
84
76
|
* @returns - true if integrity is enabled, false otherwise
|
|
85
77
|
*/
|
|
86
|
-
async function isProjectIntegrityEnabled(integrityFilePath) {
|
|
87
|
-
if (!
|
|
78
|
+
export async function isProjectIntegrityEnabled(integrityFilePath) {
|
|
79
|
+
if (!existsSync(integrityFilePath)) {
|
|
88
80
|
throw new Error(`Integrity data not found at ${integrityFilePath}`);
|
|
89
81
|
}
|
|
90
|
-
const { enabled } = await
|
|
82
|
+
const { enabled } = await readIntegrityData(integrityFilePath);
|
|
91
83
|
return enabled;
|
|
92
84
|
}
|
|
93
85
|
/**
|
|
@@ -96,14 +88,14 @@ async function isProjectIntegrityEnabled(integrityFilePath) {
|
|
|
96
88
|
*
|
|
97
89
|
* @param integrityFilePath - path to file where integrity data is stored
|
|
98
90
|
*/
|
|
99
|
-
async function enableProjectIntegrity(integrityFilePath) {
|
|
100
|
-
if (!
|
|
91
|
+
export async function enableProjectIntegrity(integrityFilePath) {
|
|
92
|
+
if (!existsSync(integrityFilePath)) {
|
|
101
93
|
throw new Error(`Integrity data not found at ${integrityFilePath}`);
|
|
102
94
|
}
|
|
103
|
-
const integrityData = await
|
|
95
|
+
const integrityData = await readIntegrityData(integrityFilePath);
|
|
104
96
|
if (!integrityData.enabled) {
|
|
105
97
|
integrityData.enabled = true;
|
|
106
|
-
await
|
|
98
|
+
await writeIntegrityData(integrityFilePath, integrityData);
|
|
107
99
|
}
|
|
108
100
|
}
|
|
109
101
|
/**
|
|
@@ -111,14 +103,14 @@ async function enableProjectIntegrity(integrityFilePath) {
|
|
|
111
103
|
*
|
|
112
104
|
* @param integrityFilePath - path to file where integrity data is stored
|
|
113
105
|
*/
|
|
114
|
-
async function disableProjectIntegrity(integrityFilePath) {
|
|
115
|
-
if (!
|
|
106
|
+
export async function disableProjectIntegrity(integrityFilePath) {
|
|
107
|
+
if (!existsSync(integrityFilePath)) {
|
|
116
108
|
throw new Error(`Integrity data not found at ${integrityFilePath}`);
|
|
117
109
|
}
|
|
118
|
-
const integrityData = await
|
|
110
|
+
const integrityData = await readIntegrityData(integrityFilePath);
|
|
119
111
|
if (integrityData.enabled) {
|
|
120
112
|
integrityData.enabled = false;
|
|
121
|
-
await
|
|
113
|
+
await writeIntegrityData(integrityFilePath, integrityData);
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
116
|
//# sourceMappingURL=project.js.map
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap-ux/project-integrity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Library to check the integrity of projects",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"repository": {
|
|
6
7
|
"type": "git",
|
|
7
8
|
"url": "https://github.com/SAP/open-ux-tools.git",
|
|
@@ -24,7 +25,10 @@
|
|
|
24
25
|
},
|
|
25
26
|
"dependencies": {
|
|
26
27
|
"lz-string": "1.5.0",
|
|
27
|
-
"@sap-ux/project-access": "
|
|
28
|
+
"@sap-ux/project-access": "2.0.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@jest/globals": "30.3.0"
|
|
28
32
|
},
|
|
29
33
|
"scripts": {
|
|
30
34
|
"build": "tsc --build",
|
|
@@ -32,7 +36,7 @@
|
|
|
32
36
|
"format": "prettier --write '**/*.{js,json,ts,yaml,yml}' --ignore-path ../../.prettierignore",
|
|
33
37
|
"lint": "eslint",
|
|
34
38
|
"lint:fix": "eslint --fix",
|
|
35
|
-
"test": "jest --ci --forceExit --detectOpenHandles --colors",
|
|
39
|
+
"test": "cross-env NODE_OPTIONS='--experimental-vm-modules' jest --ci --forceExit --detectOpenHandles --colors",
|
|
36
40
|
"watch": "tsc --watch"
|
|
37
41
|
}
|
|
38
42
|
}
|