From 1cbe13898772342e65913abc1ee068aa782c61b2 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Wed, 25 Sep 2024 15:32:02 +0300 Subject: [PATCH 01/11] add mondaycoderc check --- package.json | 3 +- src/assets/mondaycodercSchema.json | 95 ++++++++++++++++++++++++++++++ src/services/files-service.ts | 34 +++++++---- tsconfig.json | 4 ++ yarn.lock | 56 +++++++++++++++++- 5 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 src/assets/mondaycodercSchema.json diff --git a/package.json b/package.json index 46d9f54..d5f5d8c 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mondaycom/apps-cli", - "version": "4.1.1", + "version": "4.1.2", "description": "A cli tool to manage apps (and monday-code projects) in monday.com", "author": "monday.com Apps Team", "type": "module", @@ -53,6 +53,7 @@ "@oclif/core": "^3.18.1", "@oclif/plugin-autocomplete": "^3.0.5", "@oclif/plugin-help": "^6.0.12", + "ajv": "^8.17.1", "archiver": "^5.3.1", "args-parser": "^1.3.0", "axios": "^1.6.5", diff --git a/src/assets/mondaycodercSchema.json b/src/assets/mondaycodercSchema.json new file mode 100644 index 0000000..dd12346 --- /dev/null +++ b/src/assets/mondaycodercSchema.json @@ -0,0 +1,95 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "RUNTIME": { + "type": "string", + "enum": ["Python", "Java", "Go", "PHP", "Ruby", "Nodejs", "NETCore"] + }, + "RUNTIME_VERSION": { + "type": "string" + } + }, + "dependencies": { + "RUNTIME": ["RUNTIME_VERSION"] + }, + "allOf": [ + { + "if": { "properties": { "RUNTIME": { "const": "Python" } } }, + "then": { + "properties": { + "RUNTIME_VERSION": { + "type": "string", + "pattern": "^3\\.(10|11|12)\\.\\d+$" + } + } + } + }, + { + "if": { "properties": { "RUNTIME": { "const": "Java" } } }, + "then": { + "properties": { + "RUNTIME_VERSION": { + "type": "string", + "enum": ["11", "17", "18"] + } + } + } + }, + { + "if": { "properties": { "RUNTIME": { "const": "Go" } } }, + "then": { + "properties": { + "RUNTIME_VERSION": { + "type": "string", + "pattern": "^1\\.\\d+.\\d+$" + } + } + } + }, + { + "if": { "properties": { "RUNTIME": { "const": "PHP" } } }, + "then": { + "properties": { + "RUNTIME_VERSION": { + "type": "string", + "pattern": "^8\\.(1|2)\\.\\d+$" + } + } + } + }, + { + "if": { "properties": { "RUNTIME": { "const": "Ruby" } } }, + "then": { + "properties": { + "RUNTIME_VERSION": { + "type": "string", + "pattern": "^3\\.(1|2)\\.\\d+$" + } + } + } + }, + { + "if": { "properties": { "RUNTIME": { "const": "Nodejs" } } }, + "then": { + "properties": { + "RUNTIME_VERSION": { + "type": "string", + "pattern": "^(12|14|16|18|20)\\.\\d+\\.\\d+$" + } + } + } + }, + { + "if": { "properties": { "RUNTIME": { "const": "NETCore" } } }, + "then": { + "properties": { + "RUNTIME_VERSION": { + "type": "string", + "pattern": "^(6|7)\\.\\d+$" + } + } + } + } + ] +} diff --git a/src/services/files-service.ts b/src/services/files-service.ts index 0ac65cb..2e09203 100644 --- a/src/services/files-service.ts +++ b/src/services/files-service.ts @@ -2,10 +2,12 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; +import Ajv from 'ajv'; import archiver from 'archiver'; import glob from 'glob'; import parseGitIgnore from 'parse-gitignore'; +import rcFileSchema from 'assets/mondaycodercSchema.json'; import { CONFIG_NAME } from 'services/config-service'; import logger from '../utils/logger.js'; @@ -113,18 +115,30 @@ export const createGitignoreAndAppendConfigFileIfNeeded = (directoryPath: string **/ export const validateIfCanBuild = (directoryPath: string): void => { const filePath = path.join(directoryPath, 'yarn.lock'); - if (!checkIfFileExists(filePath)) { - return; + if (checkIfFileExists(filePath)) { + const packageJsonPath = path.join(directoryPath, 'package.json'); + const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8'); + const packageJson = JSON.parse(packageJsonContent) as { scripts?: { build?: string } }; + const hasBuildCommand = packageJson?.scripts?.build; + if (hasBuildCommand) { + throw new Error( + 'monday-code does not support yarn projects with a build command. If you need a build step, use npm instead', + ); + } } - const packageJsonPath = path.join(directoryPath, 'package.json'); - const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8'); - const packageJson = JSON.parse(packageJsonContent) as { scripts?: { build?: string } }; - const hasBuildCommand = packageJson?.scripts?.build; - if (hasBuildCommand) { - throw new Error( - 'monday-code does not support yarn projects with a build command. If you need a build step, use npm instead', - ); + const rcFilePath = path.join(directoryPath, '.mondaycoderc'); + if (checkIfFileExists(rcFilePath)) { + const rcFileContent = JSON.parse(fs.readFileSync(rcFilePath, 'utf8')) as { + RUNTIME: string; + RUNTIME_VERSION: string; + }; + const ajv = new Ajv(); + const validate = ajv.compile(rcFileSchema); + const isValid = validate(rcFileContent); + if (!isValid) { + throw new Error('Invalid .mondaycoderc file'); + } } }; diff --git a/tsconfig.json b/tsconfig.json index ae35453..ca72f24 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,6 +15,7 @@ "baseUrl": ".", "strict": true, "target": "ESNext", + "resolveJsonModule": true, "lib": [ "ES2022", "DOM" @@ -46,6 +47,9 @@ ], "commands-base/*": [ "./src/commands-base/*" + ], + "assets/*": [ + "./src/assets/*" ] } }, diff --git a/yarn.lock b/yarn.lock index 94dd6aa..7ccc1f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2983,6 +2983,16 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" @@ -4978,6 +4988,11 @@ fast-safe-stringify@^2.1.1: resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== +fast-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" + integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== + fast-xml-parser@4.2.5: version "4.2.5" resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" @@ -6590,6 +6605,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" @@ -8406,6 +8426,11 @@ require-directory@^2.1.1: resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz" @@ -8884,7 +8909,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8943,7 +8977,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -9669,7 +9710,7 @@ wordwrap@^1.0.0: resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9687,6 +9728,15 @@ wrap-ansi@^6.0.1: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" From dbc56c79a7ad222caa3a6fce2596107144bbad19 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Wed, 25 Sep 2024 16:43:24 +0300 Subject: [PATCH 02/11] add resolveJsonModule to build config --- build.tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/build.tsconfig.json b/build.tsconfig.json index d3982f5..919b09a 100755 --- a/build.tsconfig.json +++ b/build.tsconfig.json @@ -7,6 +7,7 @@ "inlineSourceMap": false, "noEmit": false, "strict": true, + "resolveJsonModule": true, "paths": { "src/*": [ "./src/*" From 3cc38e42988f1036deb401419a8cc8b8f4016b88 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Wed, 25 Sep 2024 16:52:09 +0300 Subject: [PATCH 03/11] added assets path to build config --- build.tsconfig.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.tsconfig.json b/build.tsconfig.json index 919b09a..c19f224 100755 --- a/build.tsconfig.json +++ b/build.tsconfig.json @@ -7,7 +7,6 @@ "inlineSourceMap": false, "noEmit": false, "strict": true, - "resolveJsonModule": true, "paths": { "src/*": [ "./src/*" @@ -32,6 +31,9 @@ ], "commands-base/*": [ "./src/commands-base/*" + ], + "assets/*": [ + "./src/assets/*" ] } }, From 2e7ab486f8d5bf3f1d36dd9b7b43a17acb2b3110 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Wed, 25 Sep 2024 17:20:28 +0300 Subject: [PATCH 04/11] change to zod schema --- build.tsconfig.json | 3 - package.json | 1 - src/assets/mondaycodercSchema.json | 95 --------------------- src/services/files-service.ts | 10 +-- src/services/schemas/mondaycoderc-schema.ts | 45 ++++++++++ tsconfig.json | 4 - yarn.lock | 25 ------ 7 files changed, 47 insertions(+), 136 deletions(-) delete mode 100644 src/assets/mondaycodercSchema.json create mode 100644 src/services/schemas/mondaycoderc-schema.ts diff --git a/build.tsconfig.json b/build.tsconfig.json index c19f224..d3982f5 100755 --- a/build.tsconfig.json +++ b/build.tsconfig.json @@ -31,9 +31,6 @@ ], "commands-base/*": [ "./src/commands-base/*" - ], - "assets/*": [ - "./src/assets/*" ] } }, diff --git a/package.json b/package.json index d5f5d8c..a8bd50f 100755 --- a/package.json +++ b/package.json @@ -53,7 +53,6 @@ "@oclif/core": "^3.18.1", "@oclif/plugin-autocomplete": "^3.0.5", "@oclif/plugin-help": "^6.0.12", - "ajv": "^8.17.1", "archiver": "^5.3.1", "args-parser": "^1.3.0", "axios": "^1.6.5", diff --git a/src/assets/mondaycodercSchema.json b/src/assets/mondaycodercSchema.json deleted file mode 100644 index dd12346..0000000 --- a/src/assets/mondaycodercSchema.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "RUNTIME": { - "type": "string", - "enum": ["Python", "Java", "Go", "PHP", "Ruby", "Nodejs", "NETCore"] - }, - "RUNTIME_VERSION": { - "type": "string" - } - }, - "dependencies": { - "RUNTIME": ["RUNTIME_VERSION"] - }, - "allOf": [ - { - "if": { "properties": { "RUNTIME": { "const": "Python" } } }, - "then": { - "properties": { - "RUNTIME_VERSION": { - "type": "string", - "pattern": "^3\\.(10|11|12)\\.\\d+$" - } - } - } - }, - { - "if": { "properties": { "RUNTIME": { "const": "Java" } } }, - "then": { - "properties": { - "RUNTIME_VERSION": { - "type": "string", - "enum": ["11", "17", "18"] - } - } - } - }, - { - "if": { "properties": { "RUNTIME": { "const": "Go" } } }, - "then": { - "properties": { - "RUNTIME_VERSION": { - "type": "string", - "pattern": "^1\\.\\d+.\\d+$" - } - } - } - }, - { - "if": { "properties": { "RUNTIME": { "const": "PHP" } } }, - "then": { - "properties": { - "RUNTIME_VERSION": { - "type": "string", - "pattern": "^8\\.(1|2)\\.\\d+$" - } - } - } - }, - { - "if": { "properties": { "RUNTIME": { "const": "Ruby" } } }, - "then": { - "properties": { - "RUNTIME_VERSION": { - "type": "string", - "pattern": "^3\\.(1|2)\\.\\d+$" - } - } - } - }, - { - "if": { "properties": { "RUNTIME": { "const": "Nodejs" } } }, - "then": { - "properties": { - "RUNTIME_VERSION": { - "type": "string", - "pattern": "^(12|14|16|18|20)\\.\\d+\\.\\d+$" - } - } - } - }, - { - "if": { "properties": { "RUNTIME": { "const": "NETCore" } } }, - "then": { - "properties": { - "RUNTIME_VERSION": { - "type": "string", - "pattern": "^(6|7)\\.\\d+$" - } - } - } - } - ] -} diff --git a/src/services/files-service.ts b/src/services/files-service.ts index 2e09203..950c8c0 100644 --- a/src/services/files-service.ts +++ b/src/services/files-service.ts @@ -2,13 +2,12 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import Ajv from 'ajv'; import archiver from 'archiver'; import glob from 'glob'; import parseGitIgnore from 'parse-gitignore'; -import rcFileSchema from 'assets/mondaycodercSchema.json'; import { CONFIG_NAME } from 'services/config-service'; +import { mondaycodercSchema } from 'services/schemas/mondaycoderc-schema'; import logger from '../utils/logger.js'; @@ -133,12 +132,7 @@ export const validateIfCanBuild = (directoryPath: string): void => { RUNTIME: string; RUNTIME_VERSION: string; }; - const ajv = new Ajv(); - const validate = ajv.compile(rcFileSchema); - const isValid = validate(rcFileContent); - if (!isValid) { - throw new Error('Invalid .mondaycoderc file'); - } + mondaycodercSchema.parse(rcFileContent); } }; diff --git a/src/services/schemas/mondaycoderc-schema.ts b/src/services/schemas/mondaycoderc-schema.ts new file mode 100644 index 0000000..eeed94f --- /dev/null +++ b/src/services/schemas/mondaycoderc-schema.ts @@ -0,0 +1,45 @@ +import { z } from 'zod'; + +export const mondaycodercSchema = z + .object({ + RUNTIME: z.enum(['Python', 'Java', 'Go', 'PHP', 'Ruby', 'Nodejs', 'NETCore']).optional(), + RUNTIME_VERSION: z.string().optional(), + }) + .refine( + data => { + if (data.RUNTIME) { + if (data.RUNTIME === 'Python') { + return /^3\.(10|11|12)\.\d+$/.test(data.RUNTIME_VERSION || ''); + } + + if (data.RUNTIME === 'Java') { + return ['11', '17', '18'].includes(data.RUNTIME_VERSION || ''); + } + + if (data.RUNTIME === 'Go') { + return /^1\.\d+\.\d+$/.test(data.RUNTIME_VERSION || ''); + } + + if (data.RUNTIME === 'PHP') { + return /^8\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || ''); + } + + if (data.RUNTIME === 'Ruby') { + return /^3\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || ''); + } + + if (data.RUNTIME === 'Nodejs') { + return /^(12|14|16|18|20)\.\d+\.\d+$/.test(data.RUNTIME_VERSION || ''); + } + + if (data.RUNTIME === 'NETCore') { + return /^(6|7)\.\d+$/.test(data.RUNTIME_VERSION || ''); + } + } + + return true; + }, + { + message: 'Invalid RUNTIME_VERSION for the specified RUNTIME', + }, + ); diff --git a/tsconfig.json b/tsconfig.json index ca72f24..ae35453 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,6 @@ "baseUrl": ".", "strict": true, "target": "ESNext", - "resolveJsonModule": true, "lib": [ "ES2022", "DOM" @@ -47,9 +46,6 @@ ], "commands-base/*": [ "./src/commands-base/*" - ], - "assets/*": [ - "./src/assets/*" ] } }, diff --git a/yarn.lock b/yarn.lock index 7ccc1f1..f1a55cf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2983,16 +2983,6 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.17.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== - dependencies: - fast-deep-equal "^3.1.3" - fast-uri "^3.0.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz" @@ -4988,11 +4978,6 @@ fast-safe-stringify@^2.1.1: resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== -fast-uri@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" - integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== - fast-xml-parser@4.2.5: version "4.2.5" resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" @@ -6605,11 +6590,6 @@ json-schema-traverse@^0.4.1: resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" @@ -8426,11 +8406,6 @@ require-directory@^2.1.1: resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz" From 1308477fc64684d6ea9ff1e7bc45b5c0f3d5bb44 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Wed, 25 Sep 2024 20:18:34 +0300 Subject: [PATCH 05/11] added tests --- package.json | 2 +- .../__tests__/mondaycoderc-schema.test.ts | 33 +++++++++++++++++++ tsconfig.json | 4 +-- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 src/services/__tests__/mondaycoderc-schema.test.ts diff --git a/package.json b/package.json index a8bd50f..09f18cb 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mondaycom/apps-cli", - "version": "4.1.2", + "version": "4.2.0", "description": "A cli tool to manage apps (and monday-code projects) in monday.com", "author": "monday.com Apps Team", "type": "module", diff --git a/src/services/__tests__/mondaycoderc-schema.test.ts b/src/services/__tests__/mondaycoderc-schema.test.ts new file mode 100644 index 0000000..8a0e25f --- /dev/null +++ b/src/services/__tests__/mondaycoderc-schema.test.ts @@ -0,0 +1,33 @@ +import { mondaycodercSchema } from 'services/schemas/mondaycoderc-schema'; + +describe('mondaycodercSchema Validation', () => { + it('should validate a correct Python runtime and version', () => { + const data = { RUNTIME: 'Python', RUNTIME_VERSION: '3.10.1' }; + expect(() => mondaycodercSchema.parse(data)).not.toThrow(); + }); + + it('should invalidate an incorrect Python runtime version', () => { + const data = { RUNTIME: 'Python', RUNTIME_VERSION: '2.7.0' }; + expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION for the specified RUNTIME'); + }); + + it('should validate a correct Java runtime and version', () => { + const data = { RUNTIME: 'Java', RUNTIME_VERSION: '17' }; + expect(() => mondaycodercSchema.parse(data)).not.toThrow(); + }); + + it('should invalidate a missing runtime version when runtime is specified', () => { + const data = { RUNTIME: 'Java' }; + expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION for the specified RUNTIME'); + }); + + it('should validate when runtime is not specified', () => { + const data = {}; + expect(() => mondaycodercSchema.parse(data)).not.toThrow(); + }); + + it('should invalidate an incorrect Go runtime version', () => { + const data = { RUNTIME: 'Go', RUNTIME_VERSION: '2.0.0' }; + expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION for the specified RUNTIME'); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index ae35453..c114a9b 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -50,12 +50,12 @@ } }, "include": [ - "src/**/*", + "src/**/*" ], "exclude": [ "test", "node_modules", "bin", - "dist", + "dist" ] } From d17f49cac8bee294b098acb93b72e998aafd3216 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Thu, 26 Sep 2024 10:32:31 +0300 Subject: [PATCH 06/11] added invalid runtime error and test --- src/services/__tests__/mondaycoderc-schema.test.ts | 5 +++++ src/services/schemas/mondaycoderc-schema.ts | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/services/__tests__/mondaycoderc-schema.test.ts b/src/services/__tests__/mondaycoderc-schema.test.ts index 8a0e25f..f04ab51 100644 --- a/src/services/__tests__/mondaycoderc-schema.test.ts +++ b/src/services/__tests__/mondaycoderc-schema.test.ts @@ -30,4 +30,9 @@ describe('mondaycodercSchema Validation', () => { const data = { RUNTIME: 'Go', RUNTIME_VERSION: '2.0.0' }; expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION for the specified RUNTIME'); }); + + it('should invalidate an Unsupported Runtime', () => { + const data = { RUNTIME: 'Invalid', RUNTIME_VERSION: '1.0.0' }; + expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid Runtime'); + }); }); diff --git a/src/services/schemas/mondaycoderc-schema.ts b/src/services/schemas/mondaycoderc-schema.ts index eeed94f..480d38d 100644 --- a/src/services/schemas/mondaycoderc-schema.ts +++ b/src/services/schemas/mondaycoderc-schema.ts @@ -2,7 +2,13 @@ import { z } from 'zod'; export const mondaycodercSchema = z .object({ - RUNTIME: z.enum(['Python', 'Java', 'Go', 'PHP', 'Ruby', 'Nodejs', 'NETCore']).optional(), + RUNTIME: z + .enum(['Python', 'Java', 'Go', 'PHP', 'Ruby', 'Nodejs', 'NETCore'], { + errorMap: () => ({ + message: 'Invalid Runtime. Supported runtimes are Python, Java, Go, PHP, Ruby, Nodejs, NETCore', + }), + }) + .optional(), RUNTIME_VERSION: z.string().optional(), }) .refine( @@ -36,8 +42,6 @@ export const mondaycodercSchema = z return /^(6|7)\.\d+$/.test(data.RUNTIME_VERSION || ''); } } - - return true; }, { message: 'Invalid RUNTIME_VERSION for the specified RUNTIME', From 9274d6a428839043a30f55c6076e38b80c783b1f Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Sun, 29 Sep 2024 11:34:02 +0300 Subject: [PATCH 07/11] allow empty json --- src/services/schemas/mondaycoderc-schema.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/services/schemas/mondaycoderc-schema.ts b/src/services/schemas/mondaycoderc-schema.ts index 480d38d..c234321 100644 --- a/src/services/schemas/mondaycoderc-schema.ts +++ b/src/services/schemas/mondaycoderc-schema.ts @@ -42,6 +42,8 @@ export const mondaycodercSchema = z return /^(6|7)\.\d+$/.test(data.RUNTIME_VERSION || ''); } } + + return true; }, { message: 'Invalid RUNTIME_VERSION for the specified RUNTIME', From 9496b4c0e07192c45a9549ea067a2f2f8ca5328c Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Sun, 29 Sep 2024 11:42:43 +0300 Subject: [PATCH 08/11] dont allow extra properties --- src/services/schemas/mondaycoderc-schema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/schemas/mondaycoderc-schema.ts b/src/services/schemas/mondaycoderc-schema.ts index c234321..cb225ad 100644 --- a/src/services/schemas/mondaycoderc-schema.ts +++ b/src/services/schemas/mondaycoderc-schema.ts @@ -11,6 +11,7 @@ export const mondaycodercSchema = z .optional(), RUNTIME_VERSION: z.string().optional(), }) + .strict() .refine( data => { if (data.RUNTIME) { From ee012907265380d49ec1332e80f97932c389d45e Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Sun, 29 Sep 2024 17:56:00 +0300 Subject: [PATCH 09/11] code review changes --- src/commands/code/push.ts | 3 + src/services/files-service.ts | 11 ++- src/services/push-service.ts | 2 - src/services/schemas/mondaycoderc-schema.ts | 76 ++++++++++++++------- 4 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/commands/code/push.ts b/src/commands/code/push.ts index ad53356..b72a035 100644 --- a/src/commands/code/push.ts +++ b/src/commands/code/push.ts @@ -3,6 +3,8 @@ import { Flags } from '@oclif/core'; import { AuthenticatedCommand } from 'commands-base/authenticated-command'; import { APP_ID_TO_ENTER, APP_VERSION_ID_TO_ENTER } from 'consts/messages'; import { DynamicChoicesService } from 'services/dynamic-choices-service'; +import { getCurrentWorkingDirectory } from 'services/env-service'; +import { validateIfCanBuild } from 'services/files-service'; import { getTasksForServerSide } from 'services/share/deploy'; import logger from 'utils/logger'; import { addRegionToFlags, chooseRegionIfNeeded, getRegionFromString } from 'utils/region'; @@ -52,6 +54,7 @@ export default class Push extends AuthenticatedCommand { const { directoryPath, region: strRegion } = flags; const region = getRegionFromString(strRegion); let appVersionId = flags.appVersionId; + validateIfCanBuild(directoryPath || getCurrentWorkingDirectory()); try { if (!appVersionId) { diff --git a/src/services/files-service.ts b/src/services/files-service.ts index 950c8c0..6d4bba0 100644 --- a/src/services/files-service.ts +++ b/src/services/files-service.ts @@ -5,6 +5,7 @@ import path from 'node:path'; import archiver from 'archiver'; import glob from 'glob'; import parseGitIgnore from 'parse-gitignore'; +import { ZodError } from 'zod'; import { CONFIG_NAME } from 'services/config-service'; import { mondaycodercSchema } from 'services/schemas/mondaycoderc-schema'; @@ -132,7 +133,15 @@ export const validateIfCanBuild = (directoryPath: string): void => { RUNTIME: string; RUNTIME_VERSION: string; }; - mondaycodercSchema.parse(rcFileContent); + try { + mondaycodercSchema.parse(rcFileContent); + } catch (error) { + if (error instanceof ZodError) { + throw new TypeError(error.errors[0].message); + } + + throw error; + } } }; diff --git a/src/services/push-service.ts b/src/services/push-service.ts index d97e4cd..de11703 100644 --- a/src/services/push-service.ts +++ b/src/services/push-service.ts @@ -11,7 +11,6 @@ import { createTarGzArchive, readFileData, readZipFileAsBuffer, - validateIfCanBuild, verifyClientDirectory, } from 'services/files-service'; import { pollPromise } from 'services/polling-service'; @@ -192,7 +191,6 @@ export const buildAssetToDeployTask = async ( } task.output = `Building asset to deploy from "${ctx.directoryPath}" directory`; - validateIfCanBuild(ctx.directoryPath); const archivePath = await createTarGzArchive(ctx.directoryPath, 'code'); ctx.archivePath = archivePath; ctx.showPrepareEnvironmentTask = true; diff --git a/src/services/schemas/mondaycoderc-schema.ts b/src/services/schemas/mondaycoderc-schema.ts index cb225ad..5d8da28 100644 --- a/src/services/schemas/mondaycoderc-schema.ts +++ b/src/services/schemas/mondaycoderc-schema.ts @@ -5,48 +5,76 @@ export const mondaycodercSchema = z RUNTIME: z .enum(['Python', 'Java', 'Go', 'PHP', 'Ruby', 'Nodejs', 'NETCore'], { errorMap: () => ({ - message: 'Invalid Runtime. Supported runtimes are Python, Java, Go, PHP, Ruby, Nodejs, NETCore', + message: + 'Invalid Runtime in .mondaycoderc. Supported runtimes are Python, Java, Go, PHP, Ruby, Nodejs, NETCore', }), }) .optional(), RUNTIME_VERSION: z.string().optional(), }) .strict() - .refine( - data => { - if (data.RUNTIME) { - if (data.RUNTIME === 'Python') { - return /^3\.(10|11|12)\.\d+$/.test(data.RUNTIME_VERSION || ''); + .refine(data => { + if (data.RUNTIME_VERSION) { + if (data.RUNTIME === 'Python') { + if (!/^3\.(10|11|12)\.\d+$/.test(data.RUNTIME_VERSION || '')) { + throw new Error( + 'Invalid RUNTIME_VERSION for Python in .mondaycoderc. Allowed versions are 3.10.x, 3.11.x, 3.12.x', + ); } - if (data.RUNTIME === 'Java') { - return ['11', '17', '18'].includes(data.RUNTIME_VERSION || ''); + return true; + } + + if (data.RUNTIME === 'Java') { + if (!['11', '17', '18'].includes(data.RUNTIME_VERSION || '')) { + throw new Error('Invalid RUNTIME_VERSION for Java in .mondaycoderc. Allowed versions are 11, 17, 18'); } - if (data.RUNTIME === 'Go') { - return /^1\.\d+\.\d+$/.test(data.RUNTIME_VERSION || ''); + return true; + } + + if (data.RUNTIME === 'Go') { + if (!/^1\.\d+\.\d+$/.test(data.RUNTIME_VERSION || '')) { + throw new Error('Invalid RUNTIME_VERSION for Go in .mondaycoderc. Allowed versions are 1.x.x'); } - if (data.RUNTIME === 'PHP') { - return /^8\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || ''); + return true; + } + + if (data.RUNTIME === 'PHP') { + if (!/^8\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || '')) { + throw new Error('Invalid RUNTIME_VERSION for PHP in .mondaycoderc. Allowed versions are 8.1.x, 8.2.x'); } - if (data.RUNTIME === 'Ruby') { - return /^3\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || ''); + return true; + } + + if (data.RUNTIME === 'Ruby') { + if (!/^3\.(1|2)\.\d+$/.test(data.RUNTIME_VERSION || '')) { + throw new Error('Invalid RUNTIME_VERSION for Ruby in .mondaycoderc. Allowed versions are 3.1.x, 3.2.x'); } - if (data.RUNTIME === 'Nodejs') { - return /^(12|14|16|18|20)\.\d+\.\d+$/.test(data.RUNTIME_VERSION || ''); + return true; + } + + if (data.RUNTIME === 'Nodejs') { + if (!/^(12|14|16|18|20)\.\d+\.\d+$/.test(data.RUNTIME_VERSION || '')) { + throw new Error( + 'Invalid RUNTIME_VERSION for Node.js in .mondaycoderc. Allowed versions are 12.x.x, 14.x.x, 16.x.x, 18.x.x, 20.x.x', + ); } - if (data.RUNTIME === 'NETCore') { - return /^(6|7)\.\d+$/.test(data.RUNTIME_VERSION || ''); + return true; + } + + if (data.RUNTIME === 'NETCore') { + if (!/^(6|7)\.\d+$/.test(data.RUNTIME_VERSION || '')) { + throw new Error('Invalid RUNTIME_VERSION for NETCore in .mondaycoderc. Allowed versions are 6.x, 7.x'); } + + return true; } + } - return true; - }, - { - message: 'Invalid RUNTIME_VERSION for the specified RUNTIME', - }, - ); + return true; + }); From 2a803387c4429e422cba76258f09606420906268 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Sun, 29 Sep 2024 18:00:25 +0300 Subject: [PATCH 10/11] change to node.js --- src/services/schemas/mondaycoderc-schema.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/schemas/mondaycoderc-schema.ts b/src/services/schemas/mondaycoderc-schema.ts index 5d8da28..49de3b0 100644 --- a/src/services/schemas/mondaycoderc-schema.ts +++ b/src/services/schemas/mondaycoderc-schema.ts @@ -3,10 +3,10 @@ import { z } from 'zod'; export const mondaycodercSchema = z .object({ RUNTIME: z - .enum(['Python', 'Java', 'Go', 'PHP', 'Ruby', 'Nodejs', 'NETCore'], { + .enum(['Python', 'Java', 'Go', 'PHP', 'Ruby', 'Node.js', 'NETCore'], { errorMap: () => ({ message: - 'Invalid Runtime in .mondaycoderc. Supported runtimes are Python, Java, Go, PHP, Ruby, Nodejs, NETCore', + 'Invalid Runtime in .mondaycoderc. Supported runtimes are Python, Java, Go, PHP, Ruby, Node.js, NETCore', }), }) .optional(), @@ -57,7 +57,7 @@ export const mondaycodercSchema = z return true; } - if (data.RUNTIME === 'Nodejs') { + if (data.RUNTIME === 'Node.js') { if (!/^(12|14|16|18|20)\.\d+\.\d+$/.test(data.RUNTIME_VERSION || '')) { throw new Error( 'Invalid RUNTIME_VERSION for Node.js in .mondaycoderc. Allowed versions are 12.x.x, 14.x.x, 16.x.x, 18.x.x, 20.x.x', From a3a33ec696589d3a70df36549886c945bb6cc719 Mon Sep 17 00:00:00 2001 From: Daniel Vainshtein Date: Sun, 29 Sep 2024 18:02:19 +0300 Subject: [PATCH 11/11] update tests --- src/services/__tests__/mondaycoderc-schema.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/services/__tests__/mondaycoderc-schema.test.ts b/src/services/__tests__/mondaycoderc-schema.test.ts index f04ab51..cb83c88 100644 --- a/src/services/__tests__/mondaycoderc-schema.test.ts +++ b/src/services/__tests__/mondaycoderc-schema.test.ts @@ -8,7 +8,7 @@ describe('mondaycodercSchema Validation', () => { it('should invalidate an incorrect Python runtime version', () => { const data = { RUNTIME: 'Python', RUNTIME_VERSION: '2.7.0' }; - expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION for the specified RUNTIME'); + expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION'); }); it('should validate a correct Java runtime and version', () => { @@ -16,9 +16,9 @@ describe('mondaycodercSchema Validation', () => { expect(() => mondaycodercSchema.parse(data)).not.toThrow(); }); - it('should invalidate a missing runtime version when runtime is specified', () => { + it('should validate a missing runtime version when runtime is specified', () => { const data = { RUNTIME: 'Java' }; - expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION for the specified RUNTIME'); + expect(() => mondaycodercSchema.parse(data)).not.toThrow(); }); it('should validate when runtime is not specified', () => { @@ -28,7 +28,7 @@ describe('mondaycodercSchema Validation', () => { it('should invalidate an incorrect Go runtime version', () => { const data = { RUNTIME: 'Go', RUNTIME_VERSION: '2.0.0' }; - expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION for the specified RUNTIME'); + expect(() => mondaycodercSchema.parse(data)).toThrow('Invalid RUNTIME_VERSION'); }); it('should invalidate an Unsupported Runtime', () => {