@hahnpro/flow-cli 2.12.1 → 2.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  https://github.com/hahnprojects/flow
4
4
 
5
+ ```shell
6
+ flow-cli --help
7
+ flow-cli [command] --help
8
+ ```
9
+
5
10
  # Commands
6
11
 
7
12
  ## `build [projectName]`
package/lib/auth.mjs ADDED
@@ -0,0 +1,140 @@
1
+ // @ts-check
2
+ import express from 'express';
3
+ import getPort from 'get-port';
4
+ import nconf from 'nconf';
5
+ import open from 'open';
6
+ import openidClient from 'openid-client';
7
+ import { dirname, join } from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+
10
+ import { logger } from './utils.mjs';
11
+
12
+ const BASE_URL = process.env.BASE_URL || process.env.PLATFORM_URL;
13
+ const CLIENT_ID = process.env.CLIENT_ID || process.env.API_USER || 'flow-cli';
14
+ const CLIENT_SECRET = process.env.CLIENT_SECRET || process.env.API_KEY;
15
+ const REALM = process.env.REALM;
16
+ const BUFFER = 120;
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const viewsPath = join(__dirname, 'views');
20
+
21
+ let server = null;
22
+ nconf.file({ file: join(__dirname, 'config') });
23
+
24
+ export async function getAccessToken(baseUrl = BASE_URL, realm = REALM) {
25
+ checkEnvironment([
26
+ ['BASE_URL', baseUrl],
27
+ ['REALM', realm],
28
+ ]);
29
+
30
+ nconf.load();
31
+ let tokenSet = nconf.get(baseUrl.replace(/:/g, '')) || {};
32
+ if (tokenSet.access_token && tokenSet.expires_at > Date.now() / 1000 + BUFFER) {
33
+ return tokenSet.access_token;
34
+ } else {
35
+ return CLIENT_ID && CLIENT_SECRET
36
+ ? new Promise(async (resolve, reject) => {
37
+ try {
38
+ const kcIssuer = await openidClient.Issuer.discover(`${baseUrl}/auth/realms/${realm}/`);
39
+ const client = new kcIssuer.Client({ client_id: CLIENT_ID, client_secret: CLIENT_SECRET });
40
+ const tokenSet = await client.grant({ grant_type: 'client_credentials' });
41
+ nconf.set(baseUrl.replace(/:/g, ''), tokenSet);
42
+ server.close();
43
+ nconf.save((error) => {
44
+ if (error) {
45
+ logger.error(error);
46
+ }
47
+ return resolve(tokenSet.access_token);
48
+ });
49
+ } catch (error) {
50
+ return reject(error);
51
+ }
52
+ })
53
+ : login(baseUrl, realm);
54
+ }
55
+ }
56
+
57
+ export function login(baseUrl = BASE_URL, realm = REALM) {
58
+ return new Promise(async (resolve, reject) => {
59
+ checkEnvironment([
60
+ ['BASE_URL', baseUrl],
61
+ ['REALM', realm],
62
+ ]);
63
+
64
+ server = null;
65
+ const port = process.env.PORT || (await getPort({ port: 3000 }));
66
+ const redirectUri = `http://localhost:${port}/callback`;
67
+
68
+ const kcIssuer = await openidClient.Issuer.discover(`${baseUrl}/auth/realms/${realm}/`);
69
+ const client = new kcIssuer.Client({
70
+ client_id: CLIENT_ID,
71
+ redirect_uris: [redirectUri],
72
+ response_types: ['code'],
73
+ token_endpoint_auth_method: 'none',
74
+ });
75
+
76
+ const code_verifier = openidClient.generators.codeVerifier();
77
+ const code_challenge = openidClient.generators.codeChallenge(code_verifier);
78
+ const auhtUrl = client.authorizationUrl({ code_challenge, code_challenge_method: 'S256' });
79
+
80
+ const app = express();
81
+ app.use(express.static(viewsPath));
82
+ app.set('views', viewsPath);
83
+
84
+ app.get('/callback', async (request, response) => {
85
+ const parameters = client.callbackParams(request.url);
86
+ if (parameters.code) {
87
+ response.render('index.ejs', { message: 'Authentication successful', hint: 'You can close this window' });
88
+ } else {
89
+ response.render('index.ejs', { message: 'Authentication failed', hint: 'Please try again' });
90
+ }
91
+ response.end();
92
+
93
+ try {
94
+ const tokenSet = await client.callback(redirectUri, parameters, { code_verifier });
95
+ nconf.set(baseUrl.replace(/:/g, ''), tokenSet);
96
+ server.close();
97
+ nconf.save((error) => {
98
+ if (error) {
99
+ logger.error(error);
100
+ }
101
+ return resolve(tokenSet.access_token);
102
+ });
103
+ } catch (error) {
104
+ return reject(error);
105
+ }
106
+ });
107
+
108
+ server = await app.listen(port);
109
+ await open(auhtUrl);
110
+ });
111
+ }
112
+
113
+ export function logout(baseUrl = BASE_URL) {
114
+ return new Promise((resolve, reject) => {
115
+ if (baseUrl) {
116
+ // clears specified key
117
+ nconf.clear(baseUrl.replace(/:/g, ''));
118
+ } else {
119
+ // clears all keys
120
+ nconf.reset();
121
+ }
122
+ server = null;
123
+ nconf.save((error) => {
124
+ return error ? reject(error) : resolve();
125
+ });
126
+ });
127
+ }
128
+
129
+ function checkEnvironment(values) {
130
+ let missing = false;
131
+ for (const [name, value] of values) {
132
+ if (!value && !process.env[name]) {
133
+ logger.error(`"${name}" env var is required`);
134
+ missing = true;
135
+ }
136
+ }
137
+ if (missing) {
138
+ throw new Error('Missing environment varialbes');
139
+ }
140
+ }
package/lib/cli.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ // @ts-check
2
3
  import 'reflect-metadata';
3
4
  import 'dotenv/config';
4
5
 
5
6
  import archiver from 'archiver';
6
7
  import Axios from 'axios';
7
- import chalk from 'chalk';
8
8
  import { Command } from 'commander';
9
9
  import copyfiles from 'copyfiles';
10
10
  import { execa } from 'execa';
@@ -16,28 +16,16 @@ import { createRequire } from 'node:module';
16
16
  import path from 'node:path';
17
17
  import ora from 'ora';
18
18
 
19
- import { handleConvertedOutput, prepareTsFile } from './utils.mjs';
19
+ import { getAccessToken, login, logout } from './auth.mjs';
20
+ import { handleConvertedOutput, logger, prepareTsFile } from './utils.mjs';
20
21
 
21
22
  const require = createRequire(import.meta.url);
22
-
23
- const logger = {
24
- /* eslint-disable no-console */
25
- log: console.log,
26
- error: (message) => console.log(chalk.bold.red(message)),
27
- ok: (message) => console.log(chalk.bold.green(message)),
28
- /* eslint-enable no-console */
29
- };
30
-
31
- const apiUser = process.env.API_USER;
32
- const apiKey = process.env.API_KEY;
33
- const baseUrl = process.env.PLATFORM_URL;
34
- const buildDirectory = process.env.BUILD_DIR || 'dist';
35
- const realm = process.env.REALM;
36
- const authUrl = process.env.AUTH_URL || `${baseUrl}/auth/realms/${realm}/protocol/openid-connect/token`;
23
+ const BASE_URL = process.env.BASE_URL || process.env.PLATFORM_URL;
24
+ const BUILD_DIR = process.env.BUILD_DIR || 'dist';
37
25
 
38
26
  let axios;
39
27
  if (process.env.https_proxy || process.env.http_proxy) {
40
- const httpsAgent = new HttpsProxyAgent(process.env.https_proxy || process.env.http_proxy);
28
+ const httpsAgent = HttpsProxyAgent(process.env.https_proxy || process.env.http_proxy);
41
29
  axios = Axios.create({ httpsAgent, proxy: false });
42
30
  } else {
43
31
  axios = Axios;
@@ -60,7 +48,7 @@ const CMD = {
60
48
  const program = new Command();
61
49
 
62
50
  program
63
- .version('2.12.0', '-v, --version')
51
+ .version('2.13.0', '-v, --version')
64
52
  .usage('[command] [options]')
65
53
  .description('Flow Module Management Tool')
66
54
  .on('--help', () => {});
@@ -138,6 +126,35 @@ program
138
126
  }
139
127
  });
140
128
 
129
+ program
130
+ .command('login')
131
+ .option('--url <url>', 'URL of target platform')
132
+ .option('-r, --realm <realm>', 'Auth realm of target platform')
133
+ .description('Authenticate against platform')
134
+ .action(async (options) => {
135
+ try {
136
+ await login(options.url, options.realm);
137
+ process.exit(0);
138
+ } catch (error) {
139
+ if (error) logger.log(error);
140
+ process.exit(1);
141
+ }
142
+ });
143
+
144
+ program
145
+ .command('logout')
146
+ .option('--url <url>', 'URL of target platform')
147
+ .description('Remove authentication data')
148
+ .action(async (options) => {
149
+ try {
150
+ await logout(options.url);
151
+ process.exit(0);
152
+ } catch (error) {
153
+ if (error) logger.log(error);
154
+ process.exit(1);
155
+ }
156
+ });
157
+
141
158
  program
142
159
  .command('format')
143
160
  .description('Formats all typescript files according to prettier configuration')
@@ -157,7 +174,7 @@ program
157
174
  try {
158
175
  if (checkIfAll(projectName)) process.exit(1);
159
176
  const project = await findProject(projectName);
160
- await clean(buildDirectory);
177
+ await clean(BUILD_DIR);
161
178
  await exec(CMD.INSTALL, project);
162
179
  await exec(CMD.BUILD, project);
163
180
  await copyProjectFiles(project);
@@ -171,13 +188,14 @@ program
171
188
 
172
189
  program
173
190
  .command('publish-module [projectName]')
191
+ .option('--url <url>', 'URL of target platform')
192
+ .option('-r, --realm <realm>', 'Auth realm of target platform')
174
193
  .option('-f, --functions', 'publish flow functions')
175
194
  .option('-u, --update', 'update existing flow functions')
176
195
  .option('-s, --skip', 'skip modules that already exists with the current version')
177
196
  .description('Publishes specified Module to Cloud Platform')
178
197
  .action(async (projectName, options) => {
179
198
  try {
180
- if (checkEnvironmentModules()) process.exit(1);
181
199
  const projects = [];
182
200
  if (projectName === 'all') {
183
201
  for (const project of await findProjects()) {
@@ -187,15 +205,16 @@ program
187
205
  projects.push(await findProject(projectName));
188
206
  }
189
207
 
190
- await getAccessToken();
208
+ apiToken = await getAccessToken(options.url, options.realm);
209
+ logger.ok('Got Access Token');
191
210
  for (const project of projects) {
192
- await clean(buildDirectory);
211
+ await clean(BUILD_DIR);
193
212
  await exec(CMD.INSTALL, project);
194
213
  await exec(CMD.BUILD, project);
195
214
  await copyProjectFiles(project);
196
215
  await validateModule(project);
197
216
  try {
198
- await publishModule(project);
217
+ await publishModule(project, options.url);
199
218
  } catch (error) {
200
219
  if (
201
220
  options.skip &&
@@ -212,7 +231,7 @@ program
212
231
  }
213
232
  }
214
233
  if (options.functions) {
215
- await publishFunctions(project, options.update);
234
+ await publishFunctions(project, options.update, options.url);
216
235
  }
217
236
  }
218
237
  } catch (error) {
@@ -223,11 +242,12 @@ program
223
242
 
224
243
  program
225
244
  .command('publish-functions [projectName]')
245
+ .option('--url <url>', 'URL of target platform')
246
+ .option('-r, --realm <realm>', 'Auth realm of target platform')
226
247
  .option('-u, --update', 'update existing flow functions')
227
248
  .description('Publishes all Flow Functions inside specified Module to Cloud Platform')
228
249
  .action(async (projectName, options) => {
229
250
  try {
230
- if (checkEnvironmentModules()) process.exit(1);
231
251
  const projects = [];
232
252
  if (projectName === 'all') {
233
253
  for (const project of await findProjects()) {
@@ -237,9 +257,10 @@ program
237
257
  projects.push(await findProject(projectName));
238
258
  }
239
259
 
240
- await getAccessToken();
260
+ apiToken = await getAccessToken(options.url, options.realm);
261
+ logger.ok('Got Access Token');
241
262
  for (const project of projects) {
242
- await publishFunctions(project, options.update);
263
+ await publishFunctions(project, options.update, options.url);
243
264
  }
244
265
  } catch (error) {
245
266
  if (error) logger.log(error);
@@ -343,13 +364,14 @@ if (process.env.NODE_ENV !== 'test') {
343
364
 
344
365
  async function generateSchemasForFile(tsPath, jsonPath) {
345
366
  // get schema
346
- let json = JSON.parse(await fs.promises.readFile(path.join(process.cwd(), jsonPath)));
367
+ const fileContent = await fs.promises.readFile(path.join(process.cwd(), jsonPath));
368
+ let json = JSON.parse(fileContent.toString());
347
369
 
348
370
  const filePath = path.join(process.cwd(), tsPath);
349
- const tsFile = String(await fs.promises.readFile(filePath));
371
+ const tsFile = await fs.promises.readFile(filePath);
350
372
  const directory = path.dirname(filePath);
351
373
 
352
- const result = await execa('ts-node', ['-T', '--dir', directory], { input: prepareTsFile(tsFile), preferLocal: true });
374
+ const result = await execa('ts-node', ['-T', '--dir', directory], { input: prepareTsFile(tsFile.toString()), preferLocal: true });
353
375
  json = await handleConvertedOutput(result.stdout, jsonPath, json);
354
376
  await fs.promises.writeFile(path.join(process.cwd(), jsonPath), JSON.stringify(json, null, 2) + '\n');
355
377
  }
@@ -440,7 +462,7 @@ async function findProjects() {
440
462
  try {
441
463
  const package_ = await readJson(path.join(path.dirname(projectPath), 'package.json'));
442
464
  package_.location = path.posix.join(projectsRoot, file);
443
- package_.dist = path.posix.join(process.cwd(), buildDirectory, file);
465
+ package_.dist = path.posix.join(process.cwd(), BUILD_DIR, file);
444
466
  if (rootPackage) {
445
467
  package_.dependencies = { ...package_.dependencies, ...rootPackage.dependencies };
446
468
  package_.repository = rootPackage.repository;
@@ -486,31 +508,6 @@ function findProject(projectName) {
486
508
  });
487
509
  }
488
510
 
489
- async function getAccessToken() {
490
- return new Promise(async (resolve, reject) => {
491
- try {
492
- const parameters = new URLSearchParams([
493
- ['client_id', apiUser],
494
- ['client_secret', apiKey],
495
- ['grant_type', 'client_credentials'],
496
- ]);
497
- const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
498
- const response = await axios.post(authUrl, parameters.toString(), { headers });
499
- const data = response.data;
500
-
501
- if (!data || !data.access_token) {
502
- throw new Error('Could not get AccessToken');
503
- }
504
- apiToken = data.access_token;
505
- logger.ok('AccessToken acquired');
506
- return resolve();
507
- } catch (error) {
508
- handleApiError(error);
509
- return reject();
510
- }
511
- });
512
- }
513
-
514
511
  async function packageModule(project) {
515
512
  const { dist, ...package_ } = project;
516
513
  const file = path.posix.join(dist, '..', `${project.name}.zip`);
@@ -519,7 +516,7 @@ async function packageModule(project) {
519
516
  return file;
520
517
  }
521
518
 
522
- async function publishModule(project) {
519
+ async function publishModule(project, baseUrl = BASE_URL) {
523
520
  return new Promise(async (resolve, reject) => {
524
521
  const file = await packageModule(project);
525
522
 
@@ -569,7 +566,7 @@ async function validateModule(project) {
569
566
  }
570
567
  }
571
568
 
572
- async function publishFunctions(project, update) {
569
+ async function publishFunctions(project, update, baseUrl = BASE_URL) {
573
570
  return new Promise(async (resolve, reject) => {
574
571
  const globOptions = {
575
572
  cwd: project.location,
@@ -584,7 +581,7 @@ async function publishFunctions(project, update) {
584
581
  for (const file of files) {
585
582
  try {
586
583
  const data = await fs.promises.readFile(path.join(globOptions.cwd, file));
587
- const json = JSON.parse(data);
584
+ const json = JSON.parse(data.toString());
588
585
  if (json.fqn && json.category) {
589
586
  if (update) {
590
587
  try {
@@ -673,7 +670,7 @@ function getProcess(cmd) {
673
670
  function copyProjectFiles(project) {
674
671
  return new Promise((resolve, reject) => {
675
672
  copyfiles(
676
- [`${project.location}/**`, `${buildDirectory}/`],
673
+ [`${project.location}/**`, `${BUILD_DIR}/`],
677
674
  {
678
675
  exclude: [`${project.location}/*.json`, `${project.location}/**/*.ts`, `${project.location}/**/test/**`],
679
676
  up: 1,
@@ -748,31 +745,6 @@ function checkIfAll(projectName) {
748
745
  return false;
749
746
  }
750
747
 
751
- function checkEnvironmentModules() {
752
- let missing = false;
753
- if (!apiUser) {
754
- logger.error('"API_USER" env var is not set');
755
- missing = true;
756
- }
757
- if (!apiKey) {
758
- logger.error('"API_KEY" env var is not set');
759
- missing = true;
760
- }
761
- if (!baseUrl) {
762
- logger.error('"PLATFORM_URL" env var is not set');
763
- missing = true;
764
- }
765
- if (!realm) {
766
- logger.error('"REALM" env var is not set');
767
- missing = true;
768
- }
769
- if (!buildDirectory) {
770
- logger.error('"BUILD_DIR" env var is not set');
771
- missing = true;
772
- }
773
- return missing;
774
- }
775
-
776
748
  function readJson(path) {
777
749
  return new Promise((resolve, reject) => {
778
750
  fs.readFile(path, { encoding: 'utf8' }, (error, data) => {
package/lib/utils.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import chalk from 'chalk';
1
2
  import fs from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
 
@@ -183,6 +184,14 @@ export function getCodeBlocks(string_) {
183
184
  return blocks;
184
185
  }
185
186
 
187
+ export const logger = {
188
+ /* eslint-disable no-console */
189
+ log: console.log,
190
+ error: (message) => console.log(chalk.bold.red(message)),
191
+ ok: (message) => console.log(chalk.bold.green(message)),
192
+ /* eslint-enable no-console */
193
+ };
194
+
186
195
  function blockDefinitionIncludes(block, value) {
187
196
  return block.trim().split('\n', 1)[0].includes(value);
188
197
  }
@@ -0,0 +1 @@
1
+ /*! tailwindcss v3.0.23 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],select,textarea{--tw-shadow:0 0 #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-radius:0;border-width:1px;font-size:1rem;line-height:1.5rem;padding:.5rem .75rem}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,select:focus,textarea:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);border-color:#2563eb;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);outline:2px solid transparent;outline-offset:2px}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-bottom:0;padding-top:0}select{-webkit-print-color-adjust:exact;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;color-adjust:exact;padding-right:2.5rem}[multiple]{-webkit-print-color-adjust:unset;background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;color-adjust:unset;padding-right:.75rem}[type=checkbox],[type=radio]{-webkit-print-color-adjust:exact;--tw-shadow:0 0 #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-origin:border-box;border-color:#6b7280;border-width:1px;color:#2563eb;color-adjust:exact;display:inline-block;flex-shrink:0;height:1rem;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;width:1rem}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);outline:2px solid transparent;outline-offset:2px}[type=checkbox]:checked,[type=radio]:checked{background-color:currentColor;background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:transparent}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0z'/%3E%3C/svg%3E")}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=radio]:checked:focus,[type=radio]:checked:hover{background-color:currentColor;border-color:transparent}[type=checkbox]:indeterminate{background-color:currentColor;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");background-position:50%;background-repeat:no-repeat;background-size:100% 100%;border-color:transparent}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{background-color:currentColor;border-color:transparent}[type=file]{background:unset;border-color:inherit;border-radius:0;border-width:0;font-size:unset;line-height:inherit;padding:0}[type=file]:focus{outline:1px auto -webkit-focus-ring-color}*,:after,:before{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.form-input,.form-multiselect,.form-select,.form-textarea{--tw-shadow:0 0 #0000;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-radius:0;border-width:1px;font-size:1rem;line-height:1.5rem;padding:.5rem .75rem}.form-input:focus,.form-multiselect:focus,.form-select:focus,.form-textarea:focus{--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);border-color:#2563eb;box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);outline:2px solid transparent;outline-offset:2px}.form-input::-moz-placeholder,.form-textarea::-moz-placeholder{color:#6b7280;opacity:1}.form-input:-ms-input-placeholder,.form-textarea:-ms-input-placeholder{color:#6b7280;opacity:1}.form-input::placeholder,.form-textarea::placeholder{color:#6b7280;opacity:1}.form-input::-webkit-datetime-edit-fields-wrapper{padding:0}.form-input::-webkit-date-and-time-value{min-height:1.5em}.form-input::-webkit-datetime-edit,.form-input::-webkit-datetime-edit-day-field,.form-input::-webkit-datetime-edit-hour-field,.form-input::-webkit-datetime-edit-meridiem-field,.form-input::-webkit-datetime-edit-millisecond-field,.form-input::-webkit-datetime-edit-minute-field,.form-input::-webkit-datetime-edit-month-field,.form-input::-webkit-datetime-edit-second-field,.form-input::-webkit-datetime-edit-year-field{padding-bottom:0;padding-top:0}.separate{align-items:center;display:flex;text-align:center}.separate:after,.separate:before{--tw-border-opacity:1;border-bottom-width:1px;border-color:rgb(209 213 219/var(--tw-border-opacity));content:"";flex:1 1 0%}.separate:not(:empty):after{margin-left:.5rem}.separate:not(:empty):before{margin-right:.5rem}.button-wrapper{padding-top:1rem}.button-wrapper,.card{display:flex;justify-content:center}.card{flex-direction:column;min-height:100vh;width:100%}.card>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.card{background-color:hsla(0,0%,100%,.7);padding:2rem 2rem 2.5rem}@media (min-width:768px){.card{--tw-drop-shadow:drop-shadow(0 10px 8px rgba(0,0,0,.04)) drop-shadow(0 4px 3px rgba(0,0,0,.1));background-color:hsla(0,0%,100%,.9);border-radius:.5rem;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);min-height:-webkit-min-content;min-height:-moz-min-content;min-height:min-content}}.logo{background-image:url(logo_hpc.png);background-position:50%;background-repeat:no-repeat;background-size:contain;height:5rem;width:5rem}.logo.keycloak{background-image:url(logo_keycloak.svg)}.logo.sealed{background-image:url(logo_sealed.png);height:4rem;width:4rem}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.top-1\/2{top:50%}.left-3{left:.75rem}.left-0{left:0}.bottom-0{bottom:0}.-left-4{left:-1rem}.m-0{margin:0}.m-4{margin:1rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.mr-1{margin-right:.25rem}.mb-6{margin-bottom:1.5rem}.mb-4{margin-bottom:1rem}.mb-2{margin-bottom:.5rem}.block{display:block}.inline{display:inline}.flex{display:flex}.hidden{display:none}.h-screen{height:100vh}.h-full{height:100%}.h-4{height:1rem}.h-6{height:1.5rem}.max-h-80{max-height:20rem}.min-h-screen{min-height:100vh}.min-h-min{min-height:-webkit-min-content;min-height:-moz-min-content;min-height:min-content}.w-full{width:100%}.w-screen{width:100vw}.w-4{width:1rem}.w-6{width:1.5rem}.max-w-6xl{max-width:72rem}.max-w-2xl{max-width:42rem}.max-w-xs{max-width:20rem}.flex-grow{flex-grow:1}.-translate-y-1\/2{--tw-translate-y:-50%}.-translate-y-1\/2,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(2rem*var(--tw-space-y-reverse));margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.space-y-12>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(3rem*var(--tw-space-y-reverse));margin-top:calc(3rem*(1 - var(--tw-space-y-reverse)))}.overflow-y-scroll{overflow-y:scroll}.rounded{border-radius:.25rem}.rounded-md{border-radius:.375rem}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-white\/50{border-color:hsla(0,0%,100%,.5)}.border-primary-300{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.bg-white\/70{background-color:hsla(0,0%,100%,.7)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-slate-700{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-blue-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity))}.bg-green-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity))}.bg-orange-100{--tw-bg-opacity:1;background-color:rgb(255 237 213/var(--tw-bg-opacity))}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.from-slate-50{--tw-gradient-from:#f8fafc;--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to,rgba(248,250,252,0))}.to-slate-300{--tw-gradient-to:#cbd5e1}.p-8{padding:2rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.pb-10{padding-bottom:2.5rem}.pt-8{padding-top:2rem}.pb-6{padding-bottom:1.5rem}.pl-14{padding-left:3.5rem}.pt-4{padding-top:1rem}.pt-1{padding-top:.25rem}.text-center{text-align:center}.text-sm{font-size:.875rem;line-height:1.25rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-5xl{font-size:3rem;line-height:1}.text-lg{font-size:1.125rem;line-height:1.75rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-none{line-height:1}.leading-loose{line-height:2}.text-primary-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.text-primary-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity))}.text-blue-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity))}.text-green-600{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity))}.text-orange-600{--tw-text-opacity:1;color:rgb(234 88 12/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity))}.placeholder-slate-600::-moz-placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity))}.placeholder-slate-600:-ms-input-placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity))}.placeholder-slate-600::placeholder{--tw-placeholder-opacity:1;color:rgb(71 85 105/var(--tw-placeholder-opacity))}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.hover\:bg-slate-800:hover{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}.hover\:text-primary-900:hover{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.focus\:border-slate-700:focus{--tw-border-opacity:1;border-color:rgb(51 65 85/var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-primary-200:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(226 232 240/var(--tw-ring-opacity))}.focus\:ring-slate-700:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(51 65 85/var(--tw-ring-opacity))}.focus\:ring-slate-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(71 85 105/var(--tw-ring-opacity))}.focus\:ring-opacity-50:focus{--tw-ring-opacity:0.5}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}@media (min-width:768px){.md\:inline{display:inline}.md\:flex{display:flex}.md\:hidden{display:none}.md\:min-h-min{min-height:-webkit-min-content;min-height:-moz-min-content;min-height:min-content}.md\:max-w-lg{max-width:32rem}.md\:max-w-md{max-width:28rem}.md\:space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1rem*var(--tw-space-y-reverse));margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)))}.md\:rounded-lg{border-radius:.5rem}.md\:bg-white\/90{background-color:hsla(0,0%,100%,.9)}.md\:py-16{padding-bottom:4rem;padding-top:4rem}.md\:drop-shadow-lg{--tw-drop-shadow:drop-shadow(0 10px 8px rgba(0,0,0,.04)) drop-shadow(0 4px 3px rgba(0,0,0,.1));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}}
@@ -0,0 +1,22 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
4
+ <title>Authentication</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <link href="index.css" rel="stylesheet" />
7
+ </head>
8
+ <body>
9
+ <div
10
+ class="bg-gradient-to-b from-slate-50 to-slate-300 flex flex-col items-center text-primary-900 justify-center min-h-screen md:py-16"
11
+ >
12
+ <div class="w-full min-h-screen md:min-h-min md:max-w-lg md:space-y-4">
13
+ <div
14
+ class="card flex flex-col justify-center w-full min-h-screen md:min-h-min bg-white/70 md:bg-white/90 p-8 pb-10 space-y-6 md:rounded-lg md:drop-shadow-lg"
15
+ >
16
+ <div class="text-primary-800 text-center text-2xl"><%= message %></div>
17
+ <div class="text-center"><%= hint %></div>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </body>
22
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hahnpro/flow-cli",
3
- "version": "2.12.1",
3
+ "version": "2.14.1",
4
4
  "description": "CLI for managing Flow Modules",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -26,31 +26,39 @@
26
26
  "access": "public"
27
27
  },
28
28
  "dependencies": {
29
- "archiver": "^5.3.0",
30
- "axios": "^0.25.0",
31
- "chalk": "^5.0.0",
29
+ "archiver": "^5.3.1",
30
+ "axios": "^0.26.1",
31
+ "chalk": "^5.0.1",
32
32
  "class-transformer": "0.5.1",
33
33
  "class-validator": "~0.13.2",
34
34
  "class-validator-jsonschema": "^3.1.0",
35
- "commander": "^9.0.0",
35
+ "commander": "^9.2.0",
36
36
  "copyfiles": "^2.4.1",
37
37
  "dotenv": "^16.0.0",
38
- "execa": "^6.0.0",
38
+ "ejs": "^3.1.7",
39
+ "execa": "^6.1.0",
40
+ "express": "^4.17.3",
39
41
  "form-data": "^4.0.0",
40
- "glob": "^7.2.0",
41
- "https-proxy-agent": "^5.0.0",
42
- "ora": "^6.0.1",
42
+ "get-port": "^6.1.2",
43
+ "glob": "^8.0.1",
44
+ "https-proxy-agent": "^5.0.1",
45
+ "nconf": "^0.12.0",
46
+ "open": "^8.4.0",
47
+ "openid-client": "^5.1.5",
48
+ "ora": "^6.1.0",
43
49
  "reflect-metadata": "^0.1.13",
44
- "ts-node": "^10.5.0"
50
+ "ts-node": "^10.7.0"
45
51
  },
46
52
  "devDependencies": {
47
- "@types/jest": "^27.4.0",
48
- "@types/node": "^16.11.22",
49
- "eslint": "^8.8.0",
50
- "eslint-plugin-unicorn": "^40.1.0",
51
- "jest": "^27.5.0",
52
- "prettier": "^2.5.1",
53
- "typescript": "^4.5.5"
53
+ "@types/express": "^4.17.13",
54
+ "@types/jest": "^27.4.1",
55
+ "@types/nconf": "^0.10.2",
56
+ "@types/node": "^16.11.27",
57
+ "eslint": "^8.13.0",
58
+ "eslint-plugin-unicorn": "^42.0.0",
59
+ "jest": "^27.5.1",
60
+ "prettier": "^2.6.2",
61
+ "typescript": "^4.6.3"
54
62
  },
55
63
  "engines": {
56
64
  "node": "^14.13.1 || >=16.0.0"
@@ -65,6 +73,7 @@
65
73
  "rules": {
66
74
  "unicorn/no-array-reduce": "off",
67
75
  "unicorn/no-null": "off",
76
+ "unicorn/prefer-string-replace-all": "off",
68
77
  "unicorn/prefer-object-from-entries": "off",
69
78
  "no-async-promise-executor": "off",
70
79
  "no-console": "error"
@@ -72,8 +81,8 @@
72
81
  },
73
82
  "scripts": {
74
83
  "format": "prettier --write .",
75
- "lint": "eslint '*/**/*.{js,mjs}'",
84
+ "lint": "eslint '**/*.{js,mjs}'",
76
85
  "test": "jest"
77
86
  },
78
- "readme": "# `@hahnpro/flow-cli`\n\nhttps://github.com/hahnprojects/flow\n\n# Commands\n\n## `build [projectName]`\n\nBuilds specified Project.\n\n## `install [projectName]`\n\nInstalls the dependencies of the specified Project.\n\n## `format`\n\nFormats all typescript files according to prettier configuration.\n\n## `name [projectName]`\n\nInstalls Dependencies and Builds the specified Project.\n\n## `package [projectName]`\n\nBuilds specified Module and packages it as .zip File for manual upload to the platform.\n\n## `publish-module [projectName]`\n\nPublishes specified Module to Cloud Platform.\n\n- `-f`, `--functions` Publish flow functions.\n- `-u`, `--update` Update existing flow functions.\n\n## `publish-functions [projectName]`\n\nPublishes all Flow Functions inside specified Module to Cloud Platform.\n\n- `-u`, `--update` Update existing flow functions.\n\n## `serve [projectName]`\n\nBuilds and serves your Project. Rebuilding on file changes.\n\n## `start [projectName]`\n\nRuns your project.\n\n## `test [projectName]`\n\nRuns tests for your Project.\n\n## `generate-schemas [projectName]`\n\nGenerates Input, Output and Properties-Schemas for the specified project.\n\n- `--verbose` Output more information about what is being done.\n- `-h`, `--hide` Hide warnings if Input/OutputProperties classes can´t be found.\n This command generates the schemas and puts them in the `inputStreams` and `outputStreams`\n fields in the json-files of each Flow-Function. It always assumes the properties defined\n in the `Input/OutPutProperties` classes are meant for the default input/output streams.\n If your Function uses different streams you may have to change stream name manually.\n"
87
+ "readme": "# `@hahnpro/flow-cli`\n\nhttps://github.com/hahnprojects/flow\n\n```shell\nflow-cli --help\nflow-cli [command] --help\n```\n\n# Commands\n\n## `build [projectName]`\n\nBuilds specified Project.\n\n## `install [projectName]`\n\nInstalls the dependencies of the specified Project.\n\n## `format`\n\nFormats all typescript files according to prettier configuration.\n\n## `name [projectName]`\n\nInstalls Dependencies and Builds the specified Project.\n\n## `package [projectName]`\n\nBuilds specified Module and packages it as .zip File for manual upload to the platform.\n\n## `publish-module [projectName]`\n\nPublishes specified Module to Cloud Platform.\n\n- `-f`, `--functions` Publish flow functions.\n- `-u`, `--update` Update existing flow functions.\n\n## `publish-functions [projectName]`\n\nPublishes all Flow Functions inside specified Module to Cloud Platform.\n\n- `-u`, `--update` Update existing flow functions.\n\n## `serve [projectName]`\n\nBuilds and serves your Project. Rebuilding on file changes.\n\n## `start [projectName]`\n\nRuns your project.\n\n## `test [projectName]`\n\nRuns tests for your Project.\n\n## `generate-schemas [projectName]`\n\nGenerates Input, Output and Properties-Schemas for the specified project.\n\n- `--verbose` Output more information about what is being done.\n- `-h`, `--hide` Hide warnings if Input/OutputProperties classes can´t be found.\n This command generates the schemas and puts them in the `inputStreams` and `outputStreams`\n fields in the json-files of each Flow-Function. It always assumes the properties defined\n in the `Input/OutPutProperties` classes are meant for the default input/output streams.\n If your Function uses different streams you may have to change stream name manually.\n"
79
88
  }