diff --git a/package-lock.json b/package-lock.json index 5cde025c..4bc8b3ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "@nimbella/nimbella-cli", - "version": "4.2.2", + "version": "4.2.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@nimbella/nimbella-cli", - "version": "4.2.2", + "version": "4.2.3", "license": "Apache-2.0", "dependencies": { "@adobe/aio-cli-plugin-runtime": "github:nimbella/aio-cli-plugin-runtime#v2021-11-19-1", "@adobe/aio-lib-core-config": "^2.0.0", "@adobe/aio-lib-runtime": "^3.3.0", - "@nimbella/nimbella-deployer": "4.3.4", + "@nimbella/nimbella-deployer": "4.3.5", "@nimbella/storage": "^0.0.7", "@oclif/command": "^1", "@oclif/config": "^1", @@ -1751,9 +1751,9 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, "node_modules/@nimbella/nimbella-deployer": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@nimbella/nimbella-deployer/-/nimbella-deployer-4.3.4.tgz", - "integrity": "sha512-uh+oZw4s3LnGTOjIqJQ0JjDjq2oHUSNBmUDlmWnRxIGnq8kMa/V6YDHgrJ5Poc/pPmDS+bon3B2oVjcOns+a6Q==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@nimbella/nimbella-deployer/-/nimbella-deployer-4.3.5.tgz", + "integrity": "sha512-jtcf6cg4k0qjf8pSsDtGl6FuAp8fokYiY4PYmJii1bS8SLBYsGb1fY2l++oLddcC4y5oWU8hTwOt2e7TV7fTTg==", "dependencies": { "@aws-sdk/client-s3": "^3.27.0", "@nimbella/sdk": "^1.3.5", @@ -10952,9 +10952,9 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, "@nimbella/nimbella-deployer": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@nimbella/nimbella-deployer/-/nimbella-deployer-4.3.4.tgz", - "integrity": "sha512-uh+oZw4s3LnGTOjIqJQ0JjDjq2oHUSNBmUDlmWnRxIGnq8kMa/V6YDHgrJ5Poc/pPmDS+bon3B2oVjcOns+a6Q==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@nimbella/nimbella-deployer/-/nimbella-deployer-4.3.5.tgz", + "integrity": "sha512-jtcf6cg4k0qjf8pSsDtGl6FuAp8fokYiY4PYmJii1bS8SLBYsGb1fY2l++oLddcC4y5oWU8hTwOt2e7TV7fTTg==", "requires": { "@aws-sdk/client-s3": "^3.27.0", "@nimbella/sdk": "^1.3.5", diff --git a/package.json b/package.json index fa666f0c..720ddd63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nimbella/nimbella-cli", - "version": "4.2.2", + "version": "4.2.3", "description": "A comprehensive CLI for the Nimbella stack", "main": "lib/index.js", "repository": { @@ -17,7 +17,7 @@ "@adobe/aio-cli-plugin-runtime": "github:nimbella/aio-cli-plugin-runtime#v2021-11-19-1", "@adobe/aio-lib-core-config": "^2.0.0", "@adobe/aio-lib-runtime": "^3.3.0", - "@nimbella/nimbella-deployer": "4.3.4", + "@nimbella/nimbella-deployer": "4.3.5", "@nimbella/storage": "^0.0.7", "@oclif/command": "^1", "@oclif/config": "^1", diff --git a/src/generator/project.ts b/src/generator/project.ts index f7bcdc1f..7dfed225 100644 --- a/src/generator/project.ts +++ b/src/generator/project.ts @@ -31,13 +31,45 @@ const gitignores = `.nimbella __deployer__.zip __pycache__/ node_modules +package-lock.json .DS_Store ` +const ignoreForTypescript = 'lib/\n' + +// A canned package.json for a minimal typescript project +const packageJsonForTypescript = `{ + "main": "lib/hello.js", + "devDependencies": { + "typescript": "^4" + }, + "scripts": { + "build": "tsc -b" + } +} +` + +// A canned tsconfig.json for typescript project +const tsconfigJSON = `{ + "compilerOptions": { + "baseUrl": ".", + "esModuleInterop": true, + "importHelpers": true, + "module": "commonjs", + "outDir": "lib", + "rootDir": "src", + "target": "es2019" + }, + "include": [ + "src/**/*" + ] +} +` + // Working function used by project create export async function createProject(project: string, flags: any, logger: any): Promise<void> { const { overwrite, language } = flags - const { kind, sampleText } = languageToKindAndSample(language, logger) + const { kind, sampleText, ts } = languageToKindAndSample(language, logger) const validKind = await isKindAValidRuntime(kind) if (!validKind) { logger.handleError(`${language} is not a supported language`) @@ -54,15 +86,23 @@ export async function createProject(project: string, flags: any, logger: any): P } } createProjectPackage(samplePackage) - if (kind) { - generateSample(kind, projectConfig, sampleText, samplePackage) - } + const actionDir = generateSample(kind, projectConfig, sampleText, samplePackage, ts) // Write the config. renameActionsToFunctions(projectConfig) const data = yaml.safeDump(projectConfig) fs.writeFileSync(configFile, data) // Add the .gitignore - fs.writeFileSync(gitignoreFile, gitignores) + const ignores = gitignores + (ts ? ignoreForTypescript : '') + fs.writeFileSync(gitignoreFile, ignores) + // Add typescript-specific information + if (ts) { + const pjFile = path.join(actionDir, 'package.json') + fs.writeFileSync(pjFile, packageJsonForTypescript) + const tscFile = path.join(actionDir, 'tsconfig.json') + fs.writeFileSync(tscFile, tsconfigJSON) + const includeFile = path.join(actionDir, '.include') + fs.writeFileSync(includeFile, 'lib\n') + } const msgs = [ `A sample project called '${project}' was created for you.`, 'You may deploy it by running the command shown on the next line:', @@ -97,22 +137,29 @@ function configTemplate(): DeployStructure { // Convert a user-specified language name to a runtime kind plus a sample. // Handle the error case of user requesting an unsupported language. -function languageToKindAndSample(language: string, logger: any): { kind: string, sampleText: string } { +function languageToKindAndSample(language: string, logger: any): { kind: string, sampleText: string, ts: boolean } { language = language.toLowerCase() if (!languages.includes(language)) { logger.handleError(`${language} is not a supported language`) } - const kind = languageToKind(language) - return { kind, sampleText: samples[language] } + const { kind, ts } = languageToKind(language) + return { kind, sampleText: samples[language], ts } } // Generate a sample. The sample is called 'hello'. -function generateSample(kind: string, config: DeployStructure, sampleText: string, samplePackage: string) { +function generateSample(kind: string, config: DeployStructure, sampleText: string, samplePackage: string, ts: boolean): string { const [runtime] = kind.split(':') - const suffix = fileExtensionForRuntime(runtime, false) + const suffix = ts ? 'ts' : fileExtensionForRuntime(runtime, false) const actionDir = path.join(samplePackage, 'hello') fs.mkdirSync(actionDir, { recursive: true }) - const file = path.join(actionDir, `hello.${suffix}`) + let file: string + if (ts) { + const srcDir = path.join(actionDir, 'src') + fs.mkdirSync(srcDir) + file = path.join(srcDir, `hello.${suffix}`) + } else { + file = path.join(actionDir, `hello.${suffix}`) + } fs.writeFileSync(file, sampleText) const sampPkg = config.packages.find(pkg => pkg.name === 'sample') const action: ActionSpec = { @@ -127,6 +174,7 @@ function generateSample(kind: string, config: DeployStructure, sampleText: strin limits: limitsFor(runtime) } sampPkg.actions.push(action) + return actionDir } // Set time limits based on the runtime. Most runtimes are fine with the default @@ -142,30 +190,33 @@ function limitsFor(runtime: string): any { function languageToKind(language: string) { let runtime = language + let ts = false switch (language) { + case 'ts': + case 'typescript': + ts = true + runtime = 'nodejs' + break case 'js': case 'javascript': runtime = 'nodejs' break - case 'ts': - runtime = 'typescript' - break case 'py': runtime = 'python' break - case 'rb': - runtime = 'ruby' - break - case 'rs': - runtime = 'rust' - break + // case 'rb': + // runtime = 'ruby' + // break + // case 'rs': + // runtime = 'rust' + // break case 'golang': runtime = 'go' break default: break } - return `${runtime}:default` + return { kind: `${runtime}:default`, ts } } // Test whether a path in the file system is a project based on some simple heuristics. The path is known to exist.