@citolab/tspci-tao 2.0.9 → 2.3.0-alpha.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.
@@ -1,307 +1,331 @@
1
- import fs, { mkdirSync } from "fs";
2
- import path from "path";
3
- import archiver from "archiver";
4
-
5
- export const bundle = () => {
6
- const PACKAGE_ROOT_PATH = process.cwd();
7
-
8
- const PACKAGER_PATH = path.join(PACKAGE_ROOT_PATH + "/node_modules/@citolab/tspci-tao");
9
-
10
- // PROPERTIES CAN BE OVERRIDEN BY VALUES IN YOUR Package.json INSIDE YOUR PCI FOLDER
11
- // OTHER CONFIG VALUES ARE: "pciJsFile" THE BUNDLED PCI FILE DEFAULTS TO: "/dist/index.js"
12
- // AND icon WHICH CAN BE REFERENCED TO A SVG TO OVERRIDE THE 'LIKE' ICON.
13
- const propertiesToReplace = {
14
- typeIdentifier: "emptytypeIdentifier",
15
- version: "1.0.0",
16
- description: "my interaction description",
17
- label: "label",
18
- short: "short",
19
- score: ["NONE"],
20
- };
21
-
22
- const config = path.join(PACKAGE_ROOT_PATH, "package.json");
23
- if (!fs.existsSync(config)) {
24
- console.error(`cannot find package.json: ${config}`);
25
- process.exit();
26
- }
27
- const rawConfigData = fs.readFileSync(config);
28
- const packageData = JSON.parse(rawConfigData);
29
-
30
- // show warning if not specified
31
- for (const propertyName in propertiesToReplace) {
32
- if (propertyName === "typeIdentifier") {
33
- if (!packageData[propertyName]) {
34
- console.error(
35
- "'typeIdentifier' should be added as an option in package.json and should match the typeIdentifier of the PCI code file."
36
- );
37
- return;
38
- } else if (!/^[A-Za-z0-9]*$/.test(packageData[propertyName])) {
39
- console.error(
40
- "'typeIdentifier' can only contain (alpha)numeric characters. The pci does not work in TAO if typeindentifier contains a hyphen therefor we restrict all non (alpha)numeric characters. Make sure typeIdentifier of the PCI code file matches the typeidentier in package.json."
41
- );
42
- return;
43
- }
44
- } else {
45
- if (!packageData[propertyName])
46
- console.warn(
47
- `${propertyName} not specified in ${packageData.name} in package.json using ${propertiesToReplace[propertyName]}`
48
- );
49
- }
50
- }
51
-
52
- const outputDirectory = path.join(PACKAGE_ROOT_PATH, "dist");
53
- const outputDirectoryTemp = path.join(outputDirectory, "tmp");
54
-
55
- // remove directory to be sure it's empty
56
- if (fs.existsSync(outputDirectoryTemp)) {
57
- fs.rmdirSync(outputDirectoryTemp, { recursive: true });
58
- }
59
- // re-create the directory
60
- if (!fs.existsSync(outputDirectory)) {
61
- mkdirSync(outputDirectory);
62
- }
63
- if (!fs.existsSync(outputDirectoryTemp)) {
64
- mkdirSync(outputDirectoryTemp);
65
- } else {
66
- fs.rmdirSync(outputDirectoryTemp, { recursive: true });
67
- mkdirSync(outputDirectoryTemp);
68
- }
69
-
70
- // copy all toa files that will be used as base,
71
- // to override these files for a specific PCI: add them in the same structure in the tao_pci folder
72
- // of the pci.
73
-
74
-
75
- copyDirectoryRecursiveSync(path.join(PACKAGER_PATH, "toa_pci_default"), outputDirectoryTemp, false);
76
-
77
- // ---------------------------------------------------------------------
78
- // ADD THE VALUES THAT ARE SHOULD BE CONFIGURABLE WITHIN TAO
79
- // ---------------------------------------------------------------------
80
-
81
- // add variables from taoConfigValues, to be able to configurate PCI's
82
- const configPath = path.join(PACKAGE_ROOT_PATH, "src/config.json");
83
-
84
- if (fs.existsSync(configPath)) {
85
- let configValues;
86
- let configJson = JSON.parse(fs.readFileSync(configPath, "utf-8"));
87
- configValues = Object.keys(configJson).reduce((acc, elem) => {
88
- const defaultValue = configJson[elem];
89
-
90
- let type = "string";
91
- if (Number.isInteger(parseInt(defaultValue))) {
92
- type = "number";
93
- }
94
- if (isBoolean(defaultValue)) {
95
- type = "boolean";
96
- }
97
-
98
- acc.push({
99
- name: `${elem}`,
100
- type,
101
- defaultValue: `"${defaultValue}"`, // type === "number" ? `${defaultValue}` : `"${defaultValue}"`,
102
- optional: true,
103
- });
104
- return acc;
105
- }, []);
106
-
107
- // add default values in imsPciCreator.js
108
- const defaultValues = `{
109
- ${configValues
110
- .map((cv) => {
111
- return `${cv.name}: ${cv.defaultValue}`;
112
- })
113
- .join(",")}
114
- };`;
115
-
116
- // loop through properties with values that should be replaced
117
- // if the value is not in the config, the default value will be used
118
- for (const propertyName in propertiesToReplace) {
119
- propertiesToReplace[propertyName] = packageData[propertyName];
120
- }
121
-
122
- const creatorFile = path.join(outputDirectoryTemp, "imsPciCreator.js");
123
-
124
- replace_string_in_file(
125
- creatorFile,
126
- "###_FIRST_SCORING_METHOD_###",
127
- propertiesToReplace.score?.length > 0 ? propertiesToReplace.score[0] : "NONE"
128
- );
129
- replace_string_in_file(creatorFile, `'##__DEFAULT_VALUES__##'`, defaultValues);
130
-
131
- // add stuff in interaction/creator/widget/states/Question.js
132
- const variableDeclaration = `
133
- ${configValues
134
- .map((cv) => {
135
- return `var ${cv.name} = interaction.prop('${cv.name}') || ${cv.defaultValue};`;
136
- })
137
- .join("\r\n")}
138
- `;
139
-
140
- const setVariables = `
141
- ${configValues
142
- .map((cv) => {
143
- return `${cv.name} : ${cv.name},`;
144
- })
145
- .join("\r\n")}
146
- `;
147
-
148
- const callbacks = `${configValues
149
- .map((cv) => {
150
- return `${cv.name} : function(interaction, value){
151
- //update the pci property value:
152
- interaction.prop('${cv.name}', value);
153
-
154
- //trigger change event:
155
- interaction.triggerPci('${cv.name}', value);
156
- }`;
157
- })
158
- .join(",\r\n")}
159
- `;
160
-
161
- const widgetAnswerFile = path.join(outputDirectoryTemp, "interaction/creator/widget/states/Answer.js");
162
- replace_string_in_file(
163
- widgetAnswerFile,
164
- `'###_RD_TEMPLATES_###'`,
165
- JSON.stringify(propertiesToReplace.score).replace("[", "").replace("]", "")
166
- );
167
-
168
- const widgetQuestionFile = path.join(outputDirectoryTemp, "interaction/creator/widget/states/Question.js");
169
-
170
- replace_string_in_file(widgetQuestionFile, `// ##__SET_VARIABLES__##`, setVariables);
171
- replace_string_in_file(widgetQuestionFile, `// ##__DECLARE_VARIABLES__##`, variableDeclaration);
172
- replace_string_in_file(widgetQuestionFile, `// ##__CALLBACK__##`, callbacks);
173
- // add controls in
174
- const propertiesFormFile = path.join(outputDirectoryTemp, "interaction/creator/tpl/propertiesForm.tpl");
175
- const template = `${configValues
176
- .map((cv) => {
177
- const capitalizedName = cv.name.charAt(0).toUpperCase() + cv.name.slice(1);
178
- return `<label for="${cv.name}">{{__ "${capitalizedName}"}}</label>
179
- <span class="icon-help tooltipstered" data-tooltip="~ .tooltip-content:first" data-tooltip-theme="info"></span>
180
- <span class="tooltip-content">{{__ "${capitalizedName}"}}</span>
181
- <input type="text"
182
- name="${cv.name}"
183
- type="${cv.type === "string" ? "text" : cv.type === "number" ? "number" : "text"}"
184
- value="{{${cv.name}}}"
185
- placeholder="e.g. ${replaceAll(cv.defaultValue, '"', "")}"
186
- data-validate="${cv.optional ? "" : "$notEmpty"};">`;
187
- })
188
- .join("\r\n")}
189
- `;
190
- replace_string_in_file(propertiesFormFile, `<!-- ##_HTML_CONTROLS_## -->`, template);
191
- } else {
192
- console.warn("Create a config.json with properties to generate a TAO config");
193
- }
194
-
195
- // copy specific files
196
- if (fs.existsSync(path.join(PACKAGE_ROOT_PATH, "tao_pci"))) {
197
- copyDirectoryRecursiveSync(path.join(PACKAGE_ROOT_PATH, "tao_pci"), outputDirectoryTemp, false);
198
- }
199
-
200
- // files that contain values that should be replaced
201
- const filesToEdit = [
202
- "imsPciCreator.js",
203
- "imsPciCreator.json",
204
- "interaction/creator/widget/Widget.js",
205
- "interaction/creator/widget/states/states.js",
206
- "interaction/creator/widget/states/Question.js",
207
- "interaction/creator/widget/states/Correct.js",
208
- ];
209
-
210
- // loop through the files and replace values.
211
- for (const fileToEdit of filesToEdit) {
212
- for (const propertyName in propertiesToReplace) {
213
- const pathToFile = path.join(outputDirectoryTemp, fileToEdit);
214
- replace_string_in_file(pathToFile, `##${propertyName}##`, propertiesToReplace[propertyName]);
215
- }
216
- }
217
-
218
- // copy the actual PCI file
219
- const pciFile = config.main || "/dist/index.js";
220
-
221
- if (!fs.existsSync(path.join(outputDirectoryTemp, "/interaction/runtime/js"))) {
222
- mkdirSync(path.join(outputDirectoryTemp, "/interaction/runtime/js"));
223
- }
224
-
225
- fs.copyFileSync(
226
- path.join(PACKAGE_ROOT_PATH, pciFile),
227
- path.join(outputDirectoryTemp, "/interaction/runtime/js/index.js")
228
- );
229
-
230
- // the icon can be replaced by a custom icon
231
- const iconLocation = path.join(PACKAGE_ROOT_PATH, `${propertiesToReplace.typeIdentifier}.svg`);
232
- if (fs.existsSync(iconLocation)) {
233
- fs.copyFileSync(iconLocation, path.join(outputDirectoryTemp, "/interaction/creator/img/icon.svg"));
234
- } else {
235
- console.warn(
236
- `Cannot find svg file at: ${iconLocation} default icon will be used. To have a custom icon for the PCI in TAO add a svg file here: ${iconLocation}`
237
- );
238
- }
239
- // console.log(propertiesToReplace.short)
240
-
241
- // zip the folder
242
- const zipName = `tao-pci-${propertiesToReplace.typeIdentifier}_${packageData.version}.zip`;
243
- zipDirectory(outputDirectoryTemp, path.join(outputDirectory, zipName)).then(() =>
244
- // fs.rmdirSync(outputDirectoryTemp, { recursive: true });
245
- console.log(`created tao pci zip: ${zipName}`)
246
- );
247
- };
248
- function replace_string_in_file(filename, to_replace, replace_with) {
249
- var data = fs.readFileSync(filename, "utf8");
250
-
251
- var result = data.replace(new RegExp(to_replace, "g"), replace_with);
252
- fs.writeFileSync(filename, result, "utf8");
253
- }
254
-
255
- function copyDirectoryRecursiveSync(source, target) {
256
- if (!fs.lstatSync(source).isDirectory() || source.endsWith("tmp")) return;
257
- // var operation = move ? fs.renameSync : fs.copyFileSync;
258
- fs.readdirSync(source).forEach(function (itemName) {
259
- if (!(itemName.indexOf("tao-pci-") !== -1 && itemName.indexOf(".zip") !== -1)) {
260
- var sourcePath = path.join(source, itemName);
261
- var targetPath = path.join(target, itemName);
262
- if (fs.lstatSync(sourcePath).isDirectory()) {
263
- if (!fs.existsSync(targetPath) && !targetPath.toLocaleLowerCase().endsWith("tmp")) {
264
- fs.mkdirSync(targetPath);
265
- }
266
- copyDirectoryRecursiveSync(sourcePath, targetPath);
267
- } else {
268
- if (fs.existsSync(targetPath)) {
269
- fs.unlinkSync(targetPath);
270
- }
271
- fs.copyFileSync(sourcePath, targetPath, 0);
272
- }
273
- }
274
- });
275
- }
276
-
277
- function zipDirectory(sourceDir, outPath) {
278
- const archive = archiver("zip", { zlib: { level: 9 } });
279
- const stream = fs.createWriteStream(outPath);
280
-
281
- return new Promise((resolve, reject) => {
282
- archive
283
- .directory(sourceDir, false)
284
- .on("error", (err) => reject(err))
285
- .pipe(stream);
286
-
287
- stream.on("close", () => resolve());
288
- archive.finalize();
289
- });
290
- }
291
-
292
- function replaceAll(str, find, replace) {
293
- return str.replace(new RegExp(find, "g"), replace);
294
- }
295
-
296
- function isBoolean(string) {
297
- switch (string.toLowerCase().trim()) {
298
- case "true":
299
- case "yes":
300
- case "false":
301
- case "no":
302
- return true;
303
-
304
- default:
305
- return false;
306
- }
307
- }
1
+ import fs, { mkdirSync } from "fs";
2
+ import path from "path";
3
+ import archiver from "archiver";
4
+
5
+ export const bundle = () => {
6
+ const PACKAGE_ROOT_PATH = process.cwd();
7
+
8
+ const PACKAGER_PATH = path.join(PACKAGE_ROOT_PATH + "/node_modules/@citolab/tspci-tao");
9
+
10
+ // PROPERTIES CAN BE OVERRIDEN BY VALUES IN YOUR Package.json INSIDE YOUR PCI FOLDER
11
+ // OTHER CONFIG VALUES ARE: "pciJsFile" THE BUNDLED PCI FILE DEFAULTS TO: "/dist/index.js"
12
+ // AND icon WHICH CAN BE REFERENCED TO A SVG TO OVERRIDE THE 'LIKE' ICON.
13
+ const propertiesToReplace = {
14
+ typeIdentifier: "emptytypeIdentifier",
15
+ label: "label",
16
+ short: "short",
17
+ score: ["NONE"],
18
+ };
19
+
20
+ const config = path.join(PACKAGE_ROOT_PATH, "package.json");
21
+ if (!fs.existsSync(config)) {
22
+ console.error(`cannot find package.json: ${config}`);
23
+ process.exit();
24
+ }
25
+ const rawConfigData = fs.readFileSync(config);
26
+ const packageData = JSON.parse(rawConfigData);
27
+ let migrated = false;
28
+ // show warning if not specified
29
+ for (const propertyName in propertiesToReplace) {
30
+ if (!packageData.config) {
31
+ migrated = true;
32
+ packageData.config = {};
33
+ }
34
+ if (!packageData.config.tspci) {
35
+ migrated = true;
36
+ packageData.config.tspci = {};
37
+ }
38
+ if (!packageData.config.tspci[propertyName] && packageData[propertyName]) {
39
+ packageData.config.tspci[propertyName] = packageData[propertyName];
40
+ delete packageData[propertyName];
41
+ migrated = true;
42
+ }
43
+ if (propertyName === "typeIdentifier") {
44
+ if (!packageData.config.tspci[propertyName]) {
45
+ console.error(
46
+ "'typeIdentifier' should be added as an option in package.json and should match the typeIdentifier of the PCI code file."
47
+ );
48
+ return;
49
+ } else if (!/^[A-Za-z0-9]*$/.test(packageData.config.tspci[propertyName])) {
50
+ console.error(
51
+ "'typeIdentifier' can only contain (alpha)numeric characters. The pci does not work in TAO if typeindentifier contains a hyphen therefor we restrict all non (alpha)numeric characters. Make sure typeIdentifier of the PCI code file matches the typeidentier in package.json."
52
+ );
53
+ return;
54
+ }
55
+ } else {
56
+ if (!packageData.config.tspci[propertyName])
57
+ console.warn(
58
+ `${propertyName} not specified in ${packageData.name} in package.json using { config: tspci: {${propertiesToReplace[propertyName]}}`
59
+ );
60
+ }
61
+ }
62
+
63
+ propertiesToReplace.description = packageData.description;
64
+ propertiesToReplace.version = packageData.version;
65
+
66
+ if (migrated) {
67
+ console.warn('package.json has been migrated to use "{ config: { tspci: { typeIdentifier: ..., xx" properties.');
68
+ fs.writeFileSync(config, JSON.stringify(packageData, null, 2));
69
+ }
70
+
71
+ const outputDirectory = path.join(PACKAGE_ROOT_PATH, "dist");
72
+ const outputDirectoryTemp = path.join(outputDirectory, "tmp");
73
+
74
+ // remove directory to be sure it's empty
75
+ if (fs.existsSync(outputDirectoryTemp)) {
76
+ fs.rmdirSync(outputDirectoryTemp, { recursive: true });
77
+ }
78
+ // re-create the directory
79
+ if (!fs.existsSync(outputDirectory)) {
80
+ mkdirSync(outputDirectory);
81
+ }
82
+ if (!fs.existsSync(outputDirectoryTemp)) {
83
+ mkdirSync(outputDirectoryTemp);
84
+ } else {
85
+ fs.rmdirSync(outputDirectoryTemp, { recursive: true });
86
+ mkdirSync(outputDirectoryTemp);
87
+ }
88
+
89
+ // copy all toa files that will be used as base,
90
+ // to override these files for a specific PCI: add them in the same structure in the tao_pci folder
91
+ // of the pci.
92
+
93
+ copyDirectoryRecursiveSync(path.join(PACKAGER_PATH, "toa_pci_default"), outputDirectoryTemp, false);
94
+
95
+ // ---------------------------------------------------------------------
96
+ // ADD THE VALUES THAT ARE SHOULD BE CONFIGURABLE WITHIN TAO
97
+ // ---------------------------------------------------------------------
98
+
99
+ // add variables from taoConfigValues, to be able to configurate PCI's
100
+ const configPath = path.join(PACKAGE_ROOT_PATH, "src/config.json");
101
+
102
+ if (fs.existsSync(configPath)) {
103
+ let configValues;
104
+ let configJson = JSON.parse(fs.readFileSync(configPath, "utf-8"));
105
+ configValues = Object.keys(configJson).reduce((acc, elem) => {
106
+ const defaultValue = configJson[elem];
107
+
108
+ let type = "string";
109
+ if (Number.isInteger(parseInt(defaultValue))) {
110
+ type = "number";
111
+ }
112
+ if (isBoolean(defaultValue)) {
113
+ type = "boolean";
114
+ }
115
+
116
+ acc.push({
117
+ name: `${elem}`,
118
+ type,
119
+ defaultValue: `"${defaultValue}"`, // type === "number" ? `${defaultValue}` : `"${defaultValue}"`,
120
+ optional: true,
121
+ });
122
+ return acc;
123
+ }, []);
124
+
125
+ // add default values in imsPciCreator.js
126
+ const defaultValues = `{
127
+ ${configValues
128
+ .map((cv) => {
129
+ return `${cv.name}: ${cv.defaultValue}`;
130
+ })
131
+ .join(",")}
132
+ };`;
133
+
134
+ // loop through properties with values that should be replaced
135
+ // if the value is not in the config, the default value will be used
136
+ const defaultPackageJsonProperties = ["version", "description"];
137
+ for (const propertyName in propertiesToReplace) {
138
+ if (defaultPackageJsonProperties.includes(propertyName)) {
139
+ propertiesToReplace[propertyName] = packageData[propertyName];
140
+ } else {
141
+ propertiesToReplace[propertyName] = packageData.config.tspci[propertyName];
142
+ }
143
+ }
144
+
145
+ const creatorFile = path.join(outputDirectoryTemp, "imsPciCreator.js");
146
+
147
+ replace_string_in_file(
148
+ creatorFile,
149
+ "###_FIRST_SCORING_METHOD_###",
150
+ propertiesToReplace.score?.length > 0 ? propertiesToReplace.score[0] : "NONE"
151
+ );
152
+ replace_string_in_file(creatorFile, `'##__DEFAULT_VALUES__##'`, defaultValues);
153
+
154
+ // add stuff in interaction/creator/widget/states/Question.js
155
+ const variableDeclaration = `
156
+ ${configValues
157
+ .map((cv) => {
158
+ return `var ${cv.name} = interaction.prop('${cv.name}') || ${cv.defaultValue};`;
159
+ })
160
+ .join("\r\n")}
161
+ `;
162
+
163
+ const setVariables = `
164
+ ${configValues
165
+ .map((cv) => {
166
+ return `${cv.name} : ${cv.name},`;
167
+ })
168
+ .join("\r\n")}
169
+ `;
170
+
171
+ const callbacks = `${configValues
172
+ .map((cv) => {
173
+ return `${cv.name} : function(interaction, value){
174
+ //update the pci property value:
175
+ interaction.prop('${cv.name}', value);
176
+
177
+ //trigger change event:
178
+ interaction.triggerPci('${cv.name}', value);
179
+ }`;
180
+ })
181
+ .join(",\r\n")}
182
+ `;
183
+
184
+ const widgetAnswerFile = path.join(outputDirectoryTemp, "interaction/creator/widget/states/Answer.js");
185
+ replace_string_in_file(
186
+ widgetAnswerFile,
187
+ `'###_RD_TEMPLATES_###'`,
188
+ JSON.stringify(propertiesToReplace.score).replace("[", "").replace("]", "")
189
+ );
190
+
191
+ const widgetQuestionFile = path.join(outputDirectoryTemp, "interaction/creator/widget/states/Question.js");
192
+
193
+ replace_string_in_file(widgetQuestionFile, `// ##__SET_VARIABLES__##`, setVariables);
194
+ replace_string_in_file(widgetQuestionFile, `// ##__DECLARE_VARIABLES__##`, variableDeclaration);
195
+ replace_string_in_file(widgetQuestionFile, `// ##__CALLBACK__##`, callbacks);
196
+ // add controls in
197
+ const propertiesFormFile = path.join(outputDirectoryTemp, "interaction/creator/tpl/propertiesForm.tpl");
198
+ const template = `${configValues
199
+ .map((cv) => {
200
+ const capitalizedName = cv.name.charAt(0).toUpperCase() + cv.name.slice(1);
201
+ return `<label for="${cv.name}">{{__ "${capitalizedName}"}}</label>
202
+ <span class="icon-help tooltipstered" data-tooltip="~ .tooltip-content:first" data-tooltip-theme="info"></span>
203
+ <span class="tooltip-content">{{__ "${capitalizedName}"}}</span>
204
+ <input type="text"
205
+ name="${cv.name}"
206
+ type="${cv.type === "string" ? "text" : cv.type === "number" ? "number" : "text"}"
207
+ value="{{${cv.name}}}"
208
+ placeholder="e.g. ${replaceAll(cv.defaultValue, '"', "")}"
209
+ data-validate="${cv.optional ? "" : "$notEmpty"};">`;
210
+ })
211
+ .join("\r\n")}
212
+ `;
213
+ replace_string_in_file(propertiesFormFile, `<!-- ##_HTML_CONTROLS_## -->`, template);
214
+ } else {
215
+ console.warn("Create a config.json with properties to generate a TAO config");
216
+ }
217
+
218
+ // copy specific files
219
+ if (fs.existsSync(path.join(PACKAGE_ROOT_PATH, "tao_pci"))) {
220
+ copyDirectoryRecursiveSync(path.join(PACKAGE_ROOT_PATH, "tao_pci"), outputDirectoryTemp, false);
221
+ }
222
+
223
+ // files that contain values that should be replaced
224
+ const filesToEdit = [
225
+ "imsPciCreator.js",
226
+ "imsPciCreator.json",
227
+ "interaction/creator/widget/Widget.js",
228
+ "interaction/creator/widget/states/states.js",
229
+ "interaction/creator/widget/states/Question.js",
230
+ "interaction/creator/widget/states/Correct.js",
231
+ ];
232
+
233
+ // loop through the files and replace values.
234
+ for (const fileToEdit of filesToEdit) {
235
+ for (const propertyName in propertiesToReplace) {
236
+ const pathToFile = path.join(outputDirectoryTemp, fileToEdit);
237
+ replace_string_in_file(pathToFile, `##${propertyName}##`, propertiesToReplace[propertyName]);
238
+ }
239
+ }
240
+
241
+ // copy the actual PCI file
242
+ const pciFile = config.main || "/dist/index.js";
243
+
244
+ if (!fs.existsSync(path.join(outputDirectoryTemp, "/interaction/runtime/js"))) {
245
+ mkdirSync(path.join(outputDirectoryTemp, "/interaction/runtime/js"));
246
+ }
247
+
248
+ fs.copyFileSync(
249
+ path.join(PACKAGE_ROOT_PATH, pciFile),
250
+ path.join(outputDirectoryTemp, "/interaction/runtime/js/index.js")
251
+ );
252
+
253
+ // the icon can be replaced by a custom icon
254
+ const iconLocation = path.join(PACKAGE_ROOT_PATH, `${propertiesToReplace.typeIdentifier}.svg`);
255
+ if (fs.existsSync(iconLocation)) {
256
+ fs.copyFileSync(iconLocation, path.join(outputDirectoryTemp, "/interaction/creator/img/icon.svg"));
257
+ } else {
258
+ console.warn(
259
+ `Cannot find svg file at: ${iconLocation} default icon will be used. To have a custom icon for the PCI in TAO add a svg file here: ${iconLocation}`
260
+ );
261
+ }
262
+ // console.log(propertiesToReplace.short)
263
+
264
+ // zip the folder
265
+ const zipName = `tao-pci-${propertiesToReplace.typeIdentifier}_${packageData.version}.zip`;
266
+ zipDirectory(outputDirectoryTemp, path.join(outputDirectory, zipName)).then(() =>
267
+ // fs.rmdirSync(outputDirectoryTemp, { recursive: true });
268
+ console.log(`created tao pci zip: ${zipName}`)
269
+ );
270
+ };
271
+
272
+ function replace_string_in_file(filename, to_replace, replace_with) {
273
+ var data = fs.readFileSync(filename, "utf8");
274
+
275
+ var result = data.replace(new RegExp(to_replace, "g"), replace_with);
276
+ fs.writeFileSync(filename, result, "utf8");
277
+ }
278
+
279
+ function copyDirectoryRecursiveSync(source, target) {
280
+ if (!fs.lstatSync(source).isDirectory() || source.endsWith("tmp")) return;
281
+ // var operation = move ? fs.renameSync : fs.copyFileSync;
282
+ fs.readdirSync(source).forEach(function (itemName) {
283
+ if (!(itemName.indexOf("tao-pci-") !== -1 && itemName.indexOf(".zip") !== -1)) {
284
+ var sourcePath = path.join(source, itemName);
285
+ var targetPath = path.join(target, itemName);
286
+ if (fs.lstatSync(sourcePath).isDirectory()) {
287
+ if (!fs.existsSync(targetPath) && !targetPath.toLocaleLowerCase().endsWith("tmp")) {
288
+ fs.mkdirSync(targetPath);
289
+ }
290
+ copyDirectoryRecursiveSync(sourcePath, targetPath);
291
+ } else {
292
+ if (fs.existsSync(targetPath)) {
293
+ fs.unlinkSync(targetPath);
294
+ }
295
+ fs.copyFileSync(sourcePath, targetPath, 0);
296
+ }
297
+ }
298
+ });
299
+ }
300
+
301
+ function zipDirectory(sourceDir, outPath) {
302
+ const archive = archiver("zip", { zlib: { level: 9 } });
303
+ const stream = fs.createWriteStream(outPath);
304
+
305
+ return new Promise((resolve, reject) => {
306
+ archive
307
+ .directory(sourceDir, false)
308
+ .on("error", (err) => reject(err))
309
+ .pipe(stream);
310
+
311
+ stream.on("close", () => resolve());
312
+ archive.finalize();
313
+ });
314
+ }
315
+
316
+ function replaceAll(str, find, replace) {
317
+ return str.replace(new RegExp(find, "g"), replace);
318
+ }
319
+
320
+ function isBoolean(string) {
321
+ switch (string.toLowerCase().trim()) {
322
+ case "true":
323
+ case "yes":
324
+ case "false":
325
+ case "no":
326
+ return true;
327
+
328
+ default:
329
+ return false;
330
+ }
331
+ }