@fontoxml/fontoxml-development-tools 3.11.0 → 3.12.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.
Files changed (198) hide show
  1. package/README.md +4 -4
  2. package/npm-shrinkwrap.json +3804 -8292
  3. package/package.json +13 -19
  4. package/src/App.js +1 -1
  5. package/src/FdtCommand.js +3 -3
  6. package/src/FdtLicense.js +95 -114
  7. package/src/ModuleRegistrationApi.js +44 -16
  8. package/src/addCoreModulesToApp.js +8 -0
  9. package/src/modules/connectors/index.js +109 -16
  10. package/src/modules/connectors/instanceBuild/Dockerfile.build +1 -1
  11. package/src/modules/connectors/instanceBuild/Dockerfile.run +1 -1
  12. package/src/modules/connectors/instanceDevBuild/docker-compose.yml +2 -2
  13. package/src/modules/content-quality/index.js +101 -20
  14. package/src/modules/content-quality/instanceBuild/Dockerfile +1 -1
  15. package/src/modules/content-quality/instanceDevBuild/docker-compose.yml +1 -1
  16. package/src/modules/core/src/precontroller.help.js +23 -26
  17. package/src/modules/document-history/index.js +101 -20
  18. package/src/modules/document-history/instanceBuild/Dockerfile +1 -1
  19. package/src/modules/document-history/instanceDevBuild/docker-compose.yml +1 -1
  20. package/src/modules/editor/dev-cms/connectors-cms-standard/configureConnectorsCmsStandardDocumentRouter.js +10 -0
  21. package/src/modules/editor/dev-cms/connectors-cms-standard/configureDocumentHistoryGetPostRouteHandler.js +51 -0
  22. package/src/modules/editor/dev-cms/connectors-cms-standard/configureDocumentPostRouteHandler.js +65 -76
  23. package/src/modules/editor/dev-cms/connectors-cms-standard/configureDocumentPresearchPostRouteHandler.js +10 -7
  24. package/src/modules/editor/dev-cms/connectors-cms-standard/configureDocumentPreviewRouteHandler.js +10 -0
  25. package/src/modules/editor/dev-cms/connectors-cms-standard/configureDocumentRevisionGetPostRouteHandler.js +69 -0
  26. package/src/modules/editor/src/commands/command.convert.editor.controller.js +11 -4
  27. package/src/modules/editor/src/commands/command.convert.package.controller.js +11 -4
  28. package/src/modules/editor/src/getAppManifest.js +3 -3
  29. package/src/modules/editor/src/getWebpackConfig.js +13 -0
  30. package/src/modules/editor/src/webpackPlugins/CheckDeepImportsResolvePlugin.js +4 -0
  31. package/src/modules/editor-pre-7-7-0/src/api/downloadEditorSDK.js +16 -12
  32. package/src/modules/editor-pre-7-7-0/src/api/executeAndLog.js +3 -2
  33. package/src/modules/editor-pre-7-7-0/src/api/schema/compile.js +16 -22
  34. package/src/modules/editor-pre-7-7-0/src/api/schema/createSchemaPackages.js +8 -0
  35. package/src/modules/editor-pre-7-7-0/src/api/schema/getSchemaFontoJson.js +76 -48
  36. package/src/modules/editor-pre-7-7-0/src/command.schema.compile.controller.js +51 -2
  37. package/src/modules/editor-pre-7-7-0/test/api/schema/buildSchemaExperienceConfigurationModel.test.js +70 -79
  38. package/src/modules/editor-pre-7-7-0/test/api/schema/fixtures/invalid-fonto-json/fonto.json +1 -0
  39. package/src/modules/editor-pre-7-7-0/test/api/schema/getSchemaFontoJson.test.js +174 -0
  40. package/src/modules/editor-pre-7-7-0/test/schemaCompileController.test.js +205 -0
  41. package/src/modules/localization/index.js +2 -2
  42. package/src/modules/operations/src/api/getOperations.js +3 -3
  43. package/src/modules/review/index.js +103 -18
  44. package/src/modules/review/instanceBuild/Dockerfile +1 -1
  45. package/src/modules/review/instanceDevBuild/docker-compose.yml +1 -1
  46. package/src/modules/schema/src/api/getSchemaSummaries.js +2 -2
  47. package/src/modules/schema/test/getSchemaSummaries.test.js +14 -10
  48. package/src/modules/schema-compiler/index.js +99 -18
  49. package/src/modules/schema-compiler/instanceBuild/Dockerfile +1 -1
  50. package/src/modules/schema-compiler/instanceDevBuild/docker-compose.yml +1 -1
  51. package/src/modules/shared/index.js +3 -0
  52. package/src/modules/shared/package.json +14 -0
  53. package/src/modules/shared/src/addBackendDockerCommands.js +334 -0
  54. package/src/modules/shared/src/addBackendDownloadSelfContainedCommands.js +78 -0
  55. package/src/modules/shared/src/addBackendVersionsCommands.js +55 -0
  56. package/src/modules/shared/src/controller-templates/command.backend.build.controller.factory.js +273 -0
  57. package/src/modules/shared/src/controller-templates/command.backend.download-self-contained.controller.factory.js +131 -0
  58. package/src/modules/shared/src/controller-templates/command.backend.init.controller.factory.js +88 -0
  59. package/src/modules/shared/src/controller-templates/command.backend.run.controller.factory.js +420 -0
  60. package/src/modules/shared/src/controller-templates/command.backend.upgrade.controller.factory.js +79 -0
  61. package/src/modules/shared/src/controller-templates/command.backend.versions.controller.factory.js +23 -0
  62. package/src/modules/shared/src/controller-templates/docker/BackendManifest.js +42 -0
  63. package/src/modules/shared/src/controller-templates/docker/copyWhitelistedFiles.js +23 -0
  64. package/src/modules/shared/src/controller-templates/docker/dockerCleanup.js +146 -0
  65. package/src/modules/shared/src/controller-templates/docker/tryDockerLogout.js +31 -0
  66. package/src/modules/shared/src/controller-templates/docker/validateBackendInstance.js +48 -0
  67. package/src/modules/shared/src/ensureDockerCommands.js +61 -0
  68. package/src/modules/shared/src/executeAndLog.js +113 -0
  69. package/src/modules/{review/src/utilities/setEntryVisibility.js → shared/src/setFileVisibility.js} +8 -2
  70. package/src/modules/spell-checker/index.js +101 -18
  71. package/src/modules/spell-checker/instanceBuild/Dockerfile +1 -1
  72. package/src/modules/spell-checker/instanceDevBuild/docker-compose.yml +1 -1
  73. package/test/module.shared.test.js +81 -0
  74. package/src/modules/connectors/src/command.build.controller.js +0 -256
  75. package/src/modules/connectors/src/command.build.js +0 -54
  76. package/src/modules/connectors/src/command.download-self-contained.controller.js +0 -110
  77. package/src/modules/connectors/src/command.download-self-contained.js +0 -50
  78. package/src/modules/connectors/src/command.init.controller.js +0 -91
  79. package/src/modules/connectors/src/command.init.js +0 -42
  80. package/src/modules/connectors/src/command.run.controller.js +0 -462
  81. package/src/modules/connectors/src/command.run.js +0 -67
  82. package/src/modules/connectors/src/command.upgrade.controller.js +0 -52
  83. package/src/modules/connectors/src/command.upgrade.js +0 -42
  84. package/src/modules/connectors/src/command.versions.controller.js +0 -14
  85. package/src/modules/connectors/src/command.versions.js +0 -25
  86. package/src/modules/connectors/src/utilities/FontoxmlConnectorsManifest.js +0 -32
  87. package/src/modules/connectors/src/utilities/cleanup.js +0 -70
  88. package/src/modules/connectors/src/utilities/constants.js +0 -42
  89. package/src/modules/connectors/src/utilities/copyWhitelistedFiles.js +0 -22
  90. package/src/modules/connectors/src/utilities/executeAndLog.js +0 -63
  91. package/src/modules/connectors/src/utilities/getVerbosityLevel.js +0 -11
  92. package/src/modules/connectors/src/utilities/getWhitelist.js +0 -16
  93. package/src/modules/connectors/src/utilities/setEntryVisibility.js +0 -22
  94. package/src/modules/connectors/src/utilities/validateInstance.js +0 -29
  95. package/src/modules/content-quality/src/command.build.controller.js +0 -260
  96. package/src/modules/content-quality/src/command.build.js +0 -56
  97. package/src/modules/content-quality/src/command.download-self-contained.controller.js +0 -110
  98. package/src/modules/content-quality/src/command.download-self-contained.js +0 -52
  99. package/src/modules/content-quality/src/command.init.controller.js +0 -91
  100. package/src/modules/content-quality/src/command.init.js +0 -44
  101. package/src/modules/content-quality/src/command.run.controller.js +0 -444
  102. package/src/modules/content-quality/src/command.run.js +0 -64
  103. package/src/modules/content-quality/src/command.upgrade.controller.js +0 -52
  104. package/src/modules/content-quality/src/command.upgrade.js +0 -44
  105. package/src/modules/content-quality/src/command.versions.controller.js +0 -14
  106. package/src/modules/content-quality/src/command.versions.js +0 -25
  107. package/src/modules/content-quality/src/utilities/FontoxmlFcqManifest.js +0 -30
  108. package/src/modules/content-quality/src/utilities/cleanup.js +0 -70
  109. package/src/modules/content-quality/src/utilities/constants.js +0 -44
  110. package/src/modules/content-quality/src/utilities/copyWhitelistedFiles.js +0 -22
  111. package/src/modules/content-quality/src/utilities/executeAndLog.js +0 -63
  112. package/src/modules/content-quality/src/utilities/getVerbosityLevel.js +0 -11
  113. package/src/modules/content-quality/src/utilities/getWhitelist.js +0 -16
  114. package/src/modules/content-quality/src/utilities/setEntryVisibility.js +0 -22
  115. package/src/modules/content-quality/src/utilities/validateInstance.js +0 -29
  116. package/src/modules/document-history/src/command.build.controller.js +0 -260
  117. package/src/modules/document-history/src/command.build.js +0 -56
  118. package/src/modules/document-history/src/command.download-self-contained.controller.js +0 -110
  119. package/src/modules/document-history/src/command.download-self-contained.js +0 -50
  120. package/src/modules/document-history/src/command.init.controller.js +0 -91
  121. package/src/modules/document-history/src/command.init.js +0 -44
  122. package/src/modules/document-history/src/command.run.controller.js +0 -444
  123. package/src/modules/document-history/src/command.run.js +0 -64
  124. package/src/modules/document-history/src/command.upgrade.controller.js +0 -52
  125. package/src/modules/document-history/src/command.upgrade.js +0 -44
  126. package/src/modules/document-history/src/command.versions.controller.js +0 -14
  127. package/src/modules/document-history/src/command.versions.js +0 -25
  128. package/src/modules/document-history/src/utilities/FontoxmlFdhManifest.js +0 -30
  129. package/src/modules/document-history/src/utilities/cleanup.js +0 -70
  130. package/src/modules/document-history/src/utilities/constants.js +0 -44
  131. package/src/modules/document-history/src/utilities/copyWhitelistedFiles.js +0 -22
  132. package/src/modules/document-history/src/utilities/executeAndLog.js +0 -63
  133. package/src/modules/document-history/src/utilities/getVerbosityLevel.js +0 -11
  134. package/src/modules/document-history/src/utilities/getWhitelist.js +0 -16
  135. package/src/modules/document-history/src/utilities/setEntryVisibility.js +0 -22
  136. package/src/modules/document-history/src/utilities/validateInstance.js +0 -29
  137. package/src/modules/review/src/command.build.controller.js +0 -256
  138. package/src/modules/review/src/command.build.js +0 -54
  139. package/src/modules/review/src/command.download-self-contained.controller.js +0 -107
  140. package/src/modules/review/src/command.download-self-contained.js +0 -50
  141. package/src/modules/review/src/command.init.controller.js +0 -89
  142. package/src/modules/review/src/command.init.js +0 -42
  143. package/src/modules/review/src/command.run.controller.js +0 -428
  144. package/src/modules/review/src/command.run.js +0 -60
  145. package/src/modules/review/src/command.upgrade.controller.js +0 -59
  146. package/src/modules/review/src/command.upgrade.js +0 -42
  147. package/src/modules/review/src/command.versions.controller.js +0 -12
  148. package/src/modules/review/src/command.versions.js +0 -25
  149. package/src/modules/review/src/utilities/FontoxmlReviewManifest.js +0 -30
  150. package/src/modules/review/src/utilities/cleanup.js +0 -70
  151. package/src/modules/review/src/utilities/constants.js +0 -42
  152. package/src/modules/review/src/utilities/copyWhitelistedFiles.js +0 -22
  153. package/src/modules/review/src/utilities/executeAndLog.js +0 -63
  154. package/src/modules/review/src/utilities/getVerbosityLevel.js +0 -11
  155. package/src/modules/review/src/utilities/getWhitelist.js +0 -16
  156. package/src/modules/review/src/utilities/validateInstance.js +0 -45
  157. package/src/modules/schema-compiler/src/command.build.controller.js +0 -256
  158. package/src/modules/schema-compiler/src/command.build.js +0 -54
  159. package/src/modules/schema-compiler/src/command.download-self-contained.controller.js +0 -110
  160. package/src/modules/schema-compiler/src/command.download-self-contained.js +0 -50
  161. package/src/modules/schema-compiler/src/command.init.controller.js +0 -91
  162. package/src/modules/schema-compiler/src/command.init.js +0 -42
  163. package/src/modules/schema-compiler/src/command.run.controller.js +0 -430
  164. package/src/modules/schema-compiler/src/command.run.js +0 -60
  165. package/src/modules/schema-compiler/src/command.upgrade.controller.js +0 -64
  166. package/src/modules/schema-compiler/src/command.upgrade.js +0 -42
  167. package/src/modules/schema-compiler/src/command.versions.controller.js +0 -14
  168. package/src/modules/schema-compiler/src/command.versions.js +0 -25
  169. package/src/modules/schema-compiler/src/utilities/FontoxmlSchemaCompilerManifest.js +0 -32
  170. package/src/modules/schema-compiler/src/utilities/cleanup.js +0 -70
  171. package/src/modules/schema-compiler/src/utilities/constants.js +0 -43
  172. package/src/modules/schema-compiler/src/utilities/copyWhitelistedFiles.js +0 -22
  173. package/src/modules/schema-compiler/src/utilities/executeAndLog.js +0 -63
  174. package/src/modules/schema-compiler/src/utilities/getVerbosityLevel.js +0 -11
  175. package/src/modules/schema-compiler/src/utilities/getWhitelist.js +0 -16
  176. package/src/modules/schema-compiler/src/utilities/setEntryVisibility.js +0 -22
  177. package/src/modules/schema-compiler/src/utilities/validateInstance.js +0 -47
  178. package/src/modules/spell-checker/src/command.build.controller.js +0 -257
  179. package/src/modules/spell-checker/src/command.build.js +0 -54
  180. package/src/modules/spell-checker/src/command.download-self-contained.controller.js +0 -110
  181. package/src/modules/spell-checker/src/command.download-self-contained.js +0 -50
  182. package/src/modules/spell-checker/src/command.init.controller.js +0 -91
  183. package/src/modules/spell-checker/src/command.init.js +0 -42
  184. package/src/modules/spell-checker/src/command.run.controller.js +0 -430
  185. package/src/modules/spell-checker/src/command.run.js +0 -62
  186. package/src/modules/spell-checker/src/command.upgrade.controller.js +0 -61
  187. package/src/modules/spell-checker/src/command.upgrade.js +0 -42
  188. package/src/modules/spell-checker/src/command.versions.controller.js +0 -14
  189. package/src/modules/spell-checker/src/command.versions.js +0 -25
  190. package/src/modules/spell-checker/src/utilities/FontoxmlSpellCheckerManifest.js +0 -32
  191. package/src/modules/spell-checker/src/utilities/cleanup.js +0 -70
  192. package/src/modules/spell-checker/src/utilities/constants.js +0 -42
  193. package/src/modules/spell-checker/src/utilities/copyWhitelistedFiles.js +0 -22
  194. package/src/modules/spell-checker/src/utilities/executeAndLog.js +0 -63
  195. package/src/modules/spell-checker/src/utilities/getVerbosityLevel.js +0 -11
  196. package/src/modules/spell-checker/src/utilities/getWhitelist.js +0 -16
  197. package/src/modules/spell-checker/src/utilities/setEntryVisibility.js +0 -22
  198. package/src/modules/spell-checker/src/utilities/validateInstance.js +0 -47
@@ -0,0 +1,420 @@
1
+ import fs from 'fs-extra';
2
+ import os from 'os';
3
+ import path from 'path';
4
+
5
+ import ensureDockerCommands from '../ensureDockerCommands.js';
6
+ import executeAndLog, {
7
+ getVerbosityLevel,
8
+ VERBOSITY_LEVEL,
9
+ } from '../executeAndLog.js';
10
+ import setFileVisibility from '../setFileVisibility.js';
11
+ import BackendManifest from './docker/BackendManifest.js';
12
+ import copyWhitelistedFiles from './docker/copyWhitelistedFiles.js';
13
+ import dockerCleanup from './docker/dockerCleanup.js';
14
+ import tryDockerLogout from './docker/tryDockerLogout.js';
15
+ import validateBackendInstance from './docker/validateBackendInstance.js';
16
+
17
+ /** @typedef {import('../addBackendDockerCommands').AddBackendDockerCommandsOptions} AddBackendDockerCommandsOptions */
18
+
19
+ /**
20
+ * @param {string} configurationFilePath
21
+ * @param {string} tempDir
22
+ * @param {{[key: string]: string}} debugEnvEntries
23
+ * @param {number} verbosityLevel
24
+ * @param {FdtResponse} res
25
+ *
26
+ * @return {Promise<void>}
27
+ */
28
+ async function copyConfiguration(
29
+ configurationFilePath,
30
+ tempDir,
31
+ debugEnvEntries,
32
+ verbosityLevel,
33
+ res
34
+ ) {
35
+ const targetConfiguration = path.join(tempDir, '.env');
36
+
37
+ const exists = await fs.exists(configurationFilePath);
38
+
39
+ // Read the configuration entries from the .env file or initialize an empty array.
40
+ const configurationEntries = exists
41
+ ? await fs
42
+ .readFile(configurationFilePath, 'utf8')
43
+ .then((data) => data.split(/\r?\n/g))
44
+ : [];
45
+
46
+ // Replace or set the defaults for verbosity.
47
+ if (verbosityLevel === VERBOSITY_LEVEL.DEBUG) {
48
+ Object.keys(debugEnvEntries).forEach((key) => {
49
+ const configurationEntryIndex = configurationEntries.findIndex(
50
+ (entry) => entry.startsWith(`${key}=`)
51
+ );
52
+ const value = debugEnvEntries[key];
53
+ if (configurationEntryIndex === -1) {
54
+ configurationEntries.push(`${key}=${value}`);
55
+ } else {
56
+ configurationEntries[
57
+ configurationEntryIndex
58
+ ] = `${key}=${value}`;
59
+ }
60
+ });
61
+ }
62
+
63
+ // Ignore options that shouldn't be applied when running through FDT.
64
+ let i = configurationEntries.length;
65
+ while (i--) {
66
+ const configurationLine = configurationEntries[i];
67
+ if (
68
+ !configurationLine.startsWith('#') &&
69
+ configurationLine.indexOf('=') !== -1
70
+ ) {
71
+ const [key, _value] = configurationLine.split('=', 2);
72
+
73
+ if (key === 'ASPNETCORE_URLS') {
74
+ configurationEntries.splice(i, 1);
75
+ res.notice(
76
+ `Notice: The '${key}' configuration option in the '.env' file will be ignored when ` +
77
+ "running the application using FDT. The FDT '--port' option can be used to run the application " +
78
+ 'under a different port.'
79
+ );
80
+ }
81
+ }
82
+ }
83
+
84
+ // Write the configuration to the .env file.
85
+ const configurationData = configurationEntries.join(os.EOL);
86
+ await fs.writeFile(targetConfiguration, configurationData, 'utf8');
87
+ }
88
+
89
+ /**
90
+ * @param {AddBackendDockerCommandsOptions} options
91
+ *
92
+ * @returns {(req: AskNicelyRequest, res: FdtResponse) => Promise<void>}
93
+ */
94
+ export default function backendRunCommandFactory(options) {
95
+ return async function backendRunCommand(req, res) {
96
+ res.caption(req.command.getLongName());
97
+
98
+ const directoryPath = path.resolve(
99
+ req.options.location ? req.options.location : process.cwd()
100
+ );
101
+ const temporaryDirectoryPath = path.join(
102
+ directoryPath,
103
+ options.temporaryDirectoryName
104
+ );
105
+ const configurationFilePath = req.options['config-location']
106
+ ? path.resolve(req.options['config-location'])
107
+ : path.join(directoryPath, '.env');
108
+ const manifestFilePath = path.join(
109
+ directoryPath,
110
+ options.manifestFileName
111
+ );
112
+ const verbosityLevel = getVerbosityLevel(
113
+ req.options.verbose,
114
+ req.options.debug
115
+ );
116
+ const hasHttps = !!options.defaultHttpsPort;
117
+ const httpPort =
118
+ (hasHttps ? req.options['http-port'] : req.options.port) ||
119
+ options.defaultHttpPort;
120
+ const httpsPort = req.options['https-port'] || options.defaultHttpsPort;
121
+ const projectName = hasHttps
122
+ ? `${options.defaultImageName}_${httpPort}_${httpsPort}`
123
+ : `${options.defaultImageName}_${httpPort}`;
124
+
125
+ // Check if the working directory path exists and is a directory.
126
+ try {
127
+ const stats = await fs.stat(directoryPath);
128
+ if (!stats.isDirectory()) {
129
+ throw new res.InputError(
130
+ 'The provided location is not a directory.'
131
+ );
132
+ }
133
+ } catch (error) {
134
+ if (error.code === 'ENOENT') {
135
+ throw new res.InputError(
136
+ 'The provided location does not exist.'
137
+ );
138
+ }
139
+ throw error;
140
+ }
141
+
142
+ // Ensure that the Docker commands are available.
143
+ await ensureDockerCommands(directoryPath, res, {
144
+ checkDocker: true,
145
+ checkDockerCompose: true,
146
+ });
147
+
148
+ let pidToKillOnForceExit = null;
149
+ const setPidToKillOnForceExit = (processToKill) => {
150
+ pidToKillOnForceExit = processToKill && processToKill.pid;
151
+ };
152
+
153
+ // Ensure we cleanup before exiting on SIGINT.
154
+ let stopping = false;
155
+ process.on('SIGINT', (_code) => {
156
+ if (stopping) {
157
+ if (pidToKillOnForceExit) {
158
+ process.kill(pidToKillOnForceExit);
159
+ }
160
+ process.exit();
161
+ return;
162
+ }
163
+
164
+ stopping = true;
165
+ res.log('Gracefully stopping... (press Ctrl+C again to force)');
166
+ // eslint-disable-next-line consistent-return
167
+ return dockerCleanup(
168
+ temporaryDirectoryPath,
169
+ projectName,
170
+ res,
171
+ verbosityLevel
172
+ ).then(() => {
173
+ process.exit();
174
+ });
175
+ });
176
+
177
+ try {
178
+ await validateBackendInstance(directoryPath, options);
179
+
180
+ const configurationFileExists = await fs.exists(
181
+ configurationFilePath
182
+ );
183
+ if (!configurationFileExists) {
184
+ if (req.options['config-location']) {
185
+ throw new res.InputError(
186
+ `${options.productLabel} config "${configurationFilePath}" does not exist.`
187
+ );
188
+ }
189
+ res.notice(
190
+ `No .env file exists in the directory "${directoryPath}".${
191
+ options.documentationConfigurationGuide
192
+ ? ` Information about the .env file can be found at ${options.documentationConfigurationGuide}.`
193
+ : ''
194
+ }`
195
+ );
196
+ }
197
+
198
+ // Cleanup possible remaining resources from a previous build or run.
199
+ await dockerCleanup(
200
+ temporaryDirectoryPath,
201
+ projectName,
202
+ res,
203
+ verbosityLevel
204
+ );
205
+
206
+ const destroySpinner = res.spinner(
207
+ `Building development image at "${directoryPath}"...`
208
+ );
209
+
210
+ // Read the manifest file.
211
+ const manifestObj = await BackendManifest.fromJsonFile(
212
+ manifestFilePath,
213
+ options.manifestVersionPropertyName
214
+ );
215
+
216
+ // Retrieve data for the docker image
217
+ let dockerData;
218
+ try {
219
+ const requestObj = {
220
+ [options.licenseProductName]: {
221
+ docker: {
222
+ version: manifestObj.version,
223
+ },
224
+ },
225
+ };
226
+ const productData = await req.fdt.license.getDataForProducts(
227
+ requestObj
228
+ );
229
+ dockerData =
230
+ productData.products[options.licenseProductName].docker;
231
+ } catch (error) {
232
+ if (error.statusCode === 404) {
233
+ error.solution = `This error might be caused by requesting a nonexistent ${options.productLabel} version, please check your version.`;
234
+ }
235
+ throw error;
236
+ }
237
+
238
+ // Create a hidden temporary directory.
239
+ await fs.mkdir(temporaryDirectoryPath);
240
+ await setFileVisibility(temporaryDirectoryPath, false);
241
+ // Copy the instance files into the temporary directory.
242
+ const dockerfileContent = await fs.readFile(
243
+ options.instanceDevBuildDockerfilePath,
244
+ 'utf8'
245
+ );
246
+ // Rewrite the image in the Dockerfile.
247
+ const fixedDockerfileContent = dockerfileContent.replace(
248
+ '${image}',
249
+ dockerData.image
250
+ );
251
+ await fs.writeFile(
252
+ path.join(temporaryDirectoryPath, 'Dockerfile'),
253
+ fixedDockerfileContent,
254
+ 'utf8'
255
+ );
256
+ // Copy the dev instance files.
257
+ await fs.copy(
258
+ options.instanceDevBuildDirectoryPath,
259
+ temporaryDirectoryPath
260
+ );
261
+ // Rewrite the port in the docker-compose file.
262
+ const dockerComposeContent = await fs.readFile(
263
+ path.join(temporaryDirectoryPath, 'docker-compose.yml'),
264
+ 'utf8'
265
+ );
266
+ const fixedDockerComposeContent = dockerComposeContent
267
+ .replace('${containerName}', projectName)
268
+ .replace('${httpPort}', httpPort)
269
+ .replace('${httpsPort}', httpsPort);
270
+ await fs.writeFile(
271
+ path.join(temporaryDirectoryPath, 'docker-compose.yml'),
272
+ fixedDockerComposeContent,
273
+ 'utf8'
274
+ );
275
+ const temporaryInstanceDirectoryPath = path.join(
276
+ temporaryDirectoryPath,
277
+ 'instance'
278
+ );
279
+ await fs.ensureDir(temporaryInstanceDirectoryPath);
280
+ // Copy whitelisted files.
281
+ await copyWhitelistedFiles(
282
+ options.whitelist,
283
+ directoryPath,
284
+ temporaryInstanceDirectoryPath
285
+ );
286
+ // Copy configuration.
287
+ await copyConfiguration(
288
+ configurationFilePath,
289
+ temporaryDirectoryPath,
290
+ options.debugEnvEntries,
291
+ verbosityLevel,
292
+ res
293
+ );
294
+
295
+ // Pull the docker image.
296
+ try {
297
+ await executeAndLog(
298
+ res,
299
+ 'docker',
300
+ [
301
+ 'login',
302
+ dockerData.registry,
303
+ '-u',
304
+ dockerData.login,
305
+ '-p',
306
+ dockerData.password,
307
+ ],
308
+ null,
309
+ VERBOSITY_LEVEL.NORMAL,
310
+ false,
311
+ setPidToKillOnForceExit
312
+ );
313
+ await executeAndLog(
314
+ res,
315
+ 'docker',
316
+ ['pull', dockerData.image],
317
+ null,
318
+ verbosityLevel,
319
+ false,
320
+ setPidToKillOnForceExit
321
+ );
322
+ } catch (error) {
323
+ await tryDockerLogout(
324
+ dockerData.registry,
325
+ res,
326
+ setPidToKillOnForceExit
327
+ );
328
+ throw new res.ErrorWithInnerError(
329
+ 'Failed to retrieve the image file.',
330
+ error
331
+ );
332
+ }
333
+
334
+ // Use docker-compose to build the development image.
335
+ try {
336
+ await executeAndLog(
337
+ res,
338
+ 'docker',
339
+ verbosityLevel === VERBOSITY_LEVEL.DEBUG
340
+ ? ['compose', '-p', projectName, '--verbose', 'build']
341
+ : ['compose', '-p', projectName, 'build'],
342
+ temporaryDirectoryPath,
343
+ verbosityLevel,
344
+ false,
345
+ setPidToKillOnForceExit
346
+ );
347
+ } finally {
348
+ await tryDockerLogout(
349
+ dockerData.registry,
350
+ res,
351
+ setPidToKillOnForceExit
352
+ );
353
+ }
354
+
355
+ // Send telemetry.
356
+ await req.fdt.license.sendTelemetry({
357
+ product: req.command.parent.name,
358
+ type: 'docker',
359
+ version: manifestObj.version,
360
+ action: req.command.name,
361
+ });
362
+
363
+ destroySpinner();
364
+
365
+ // Use docker-compose to run the development image. We hard-code verbose to true since
366
+ // docker does not yet support a --quiet or --silent flag.
367
+ // See: https://github.com/docker/compose/issues/3447
368
+ res.notice(
369
+ `Starting ${
370
+ options.productLabel
371
+ } on "http://localhost:${httpPort}"${
372
+ hasHttps ? ` and http://localhost::${httpsPort}` : ''
373
+ }...`
374
+ );
375
+ await executeAndLog(
376
+ res,
377
+ 'docker',
378
+ verbosityLevel === VERBOSITY_LEVEL.DEBUG
379
+ ? ['compose', '-p', projectName, '--verbose', 'up']
380
+ : ['compose', '-p', projectName, 'up'],
381
+ temporaryDirectoryPath,
382
+ verbosityLevel,
383
+ true,
384
+ setPidToKillOnForceExit,
385
+ // Allow exit code is 130 (128 + 2 = 130; 2 coming from Control-C).
386
+ [130]
387
+ );
388
+
389
+ // Cleanup temporary directory.
390
+ await dockerCleanup(
391
+ temporaryDirectoryPath,
392
+ projectName,
393
+ res,
394
+ verbosityLevel
395
+ );
396
+ } catch (error) {
397
+ if (!stopping) {
398
+ res.notice(
399
+ options.documentationExecuteError
400
+ ? `See our documentation at ${options.documentationExecuteError} for help.`
401
+ : 'See our documentation for help.'
402
+ );
403
+ }
404
+
405
+ try {
406
+ await dockerCleanup(
407
+ temporaryDirectoryPath,
408
+ projectName,
409
+ res,
410
+ verbosityLevel
411
+ );
412
+ } catch (_cleanupError) {
413
+ // Ignore cleanup error.
414
+ }
415
+
416
+ // Re-throw the actual error.
417
+ throw error;
418
+ }
419
+ };
420
+ }
@@ -0,0 +1,79 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+
4
+ import setFileVisibility from '../setFileVisibility.js';
5
+ import BackendManifest from './docker/BackendManifest.js';
6
+
7
+ /** @typedef {import('../addBackendDockerCommands').AddBackendDockerCommandsOptions} AddBackendDockerCommandsOptions */
8
+
9
+ /**
10
+ * @param {AddBackendDockerCommandsOptions} options
11
+ *
12
+ * @returns {(req: AskNicelyRequest, res: FdtResponse) => Promise<void>}
13
+ */
14
+ export default function backendUpgradeCommandFactory(options) {
15
+ return async function backendUpgradeCommand(req, res) {
16
+ res.caption(req.command.getLongName());
17
+
18
+ // Check if the given version exist.
19
+ const sdkVersions = await req.fdt.license.getVersionsForProduct(
20
+ options.licenseProductName
21
+ );
22
+ const version = req.options.version;
23
+ if (!sdkVersions.includes(version)) {
24
+ throw new res.ErrorWithSolution(
25
+ `Could not upgrade to version (${version}), please check if it is a valid version. The latest version is ${sdkVersions.getLatestStable()}.`,
26
+ `Run \`fdt ${options.commandPrefix} versions\` to get a list of all available versions.`
27
+ );
28
+ }
29
+
30
+ const destroySpinner = res.spinner(
31
+ `Upgrading your ${options.productLabel} instance to ${version}...`
32
+ );
33
+
34
+ const directoryPath = path.resolve(
35
+ req.options.location ? req.options.location : process.cwd()
36
+ );
37
+ const manifestFilePath = path.join(
38
+ directoryPath,
39
+ options.manifestFileName
40
+ );
41
+ let currentVersion;
42
+
43
+ try {
44
+ await setFileVisibility(manifestFilePath, true);
45
+
46
+ // Read the manifest file.
47
+ const manifestObj = await BackendManifest.fromJsonFile(
48
+ manifestFilePath,
49
+ options.manifestVersionPropertyName
50
+ );
51
+
52
+ // Update the manifest file.
53
+ currentVersion = manifestObj.version;
54
+ manifestObj.version = version;
55
+ await fs.writeJson(manifestFilePath, manifestObj);
56
+
57
+ await setFileVisibility(manifestFilePath, false);
58
+
59
+ // Send telemetry.
60
+ await req.fdt.license.sendTelemetry({
61
+ product: req.command.parent.name,
62
+ type: 'docker',
63
+ version,
64
+ currentVersion,
65
+ action: req.command.name,
66
+ });
67
+
68
+ destroySpinner();
69
+ } catch (error) {
70
+ res.notice(
71
+ options.documentationExecuteError
72
+ ? `See our documentation at ${options.documentationExecuteError} for help.`
73
+ : 'See our documentation for help.'
74
+ );
75
+
76
+ throw error;
77
+ }
78
+ };
79
+ }
@@ -0,0 +1,23 @@
1
+ /** @typedef {import('../addBackendVersionsCommands').AddBackendVersionsCommandsOptions} AddBackendVersionsCommandsOptions */
2
+
3
+ /**
4
+ * @param {AddBackendVersionsCommandsOptions} options
5
+ *
6
+ * @returns {(req: AskNicelyRequest, res: FdtResponse) => Promise<void>}
7
+ */
8
+ export default function backendVersionsCommandFactory(options) {
9
+ return async function backendVersionsCommand(req, res) {
10
+ res.caption(req.command.getLongName());
11
+
12
+ const all = req.options.all;
13
+ const destroySpinner = res.spinner(
14
+ `Retrieving ${all ? 'all ' : ''}${options.productLabel} versions...`
15
+ );
16
+ const sdkVersions = await req.fdt.license.getVersionsForProduct(
17
+ options.licenseProductName
18
+ );
19
+ destroySpinner();
20
+ res.caption(`${options.productLabel} versions`);
21
+ res.list(all ? sdkVersions.getAll() : sdkVersions.getAllStable(), '-');
22
+ };
23
+ }
@@ -0,0 +1,42 @@
1
+ import fs from 'fs-extra';
2
+
3
+ export default class BackendManifest {
4
+ /**
5
+ * @param {string} versionPropertyName
6
+ * @param {string} version
7
+ */
8
+ constructor(versionPropertyName, version) {
9
+ this.versionPropertyName = versionPropertyName;
10
+ this.version = version;
11
+ }
12
+
13
+ toJSON() {
14
+ return {
15
+ [this.versionPropertyName]: this.version,
16
+ };
17
+ }
18
+
19
+ /**
20
+ * @param {string} filePath
21
+ * @param {string} versionPropertyName
22
+ *
23
+ * @return {Promise<BackendManifest>}
24
+ */
25
+ static async fromJsonFile(filePath, versionPropertyName) {
26
+ if (!(await fs.exists(filePath))) {
27
+ throw new Error(`The manifest file ${filePath} does not exist.`);
28
+ }
29
+
30
+ const json = await fs.readJson(filePath);
31
+ const version = json[versionPropertyName];
32
+ if (!version) {
33
+ throw new Error(
34
+ `The manifest file does not contain a '${versionPropertyName}'.`
35
+ );
36
+ }
37
+ return new BackendManifest(
38
+ versionPropertyName,
39
+ json[versionPropertyName]
40
+ );
41
+ }
42
+ }
@@ -0,0 +1,23 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+
4
+ /**
5
+ * @param {string[]} whitelist
6
+ * @param {string} sourceDirectory
7
+ * @param {string} destinationDirectory
8
+ *
9
+ * @return {Promise<void>}
10
+ */
11
+ export default async function copyWhitelistedFiles(
12
+ whitelist,
13
+ sourceDirectory,
14
+ destinationDirectory
15
+ ) {
16
+ for (const item of whitelist) {
17
+ const itemPath = path.join(sourceDirectory, item);
18
+ const exists = await fs.exists(itemPath);
19
+ if (exists) {
20
+ await fs.copy(itemPath, path.join(destinationDirectory, item));
21
+ }
22
+ }
23
+ }