-
Notifications
You must be signed in to change notification settings - Fork 0
feat: initial implementation #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
b2514c5
1873019
f310a98
c6fe98f
62d5035
78e8ec1
0bb961c
138911b
0aeba42
47d47dd
ce4d38e
8a5c921
48004b6
e95c61e
98afcb9
4b351a8
1b1c616
985cff2
d9afb37
1654736
ea4d56b
e29f1a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| node_modules/ | ||
| dist/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| //registry.npmjs.org/:_authToken=${NPM_TOKEN} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| { | ||
| "name": "create-functionless", | ||
| "version": "0.1.0", | ||
| "description": "Create a Functionless CDK app.", | ||
| "files": [ | ||
| "dist", | ||
| "templates/**/*" | ||
| ], | ||
| "scripts": { | ||
| "dev": "ncc build ./src/index.ts -w -o dist/", | ||
| "prerelease": "rimraf ./dist/", | ||
| "release": "ncc build ./src/index.ts -o dist/ --minify --no-cache --no-source-map-register", | ||
| "prepublishOnly": "npm run release" | ||
| }, | ||
| "keywords": [ | ||
| "functionless" | ||
| ], | ||
| "author": "Functionless", | ||
| "license": "ISC", | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "devDependencies": { | ||
| "@types/cross-spawn": "^6.0.2", | ||
| "@types/mustache": "^4.2.1", | ||
| "@types/node": "^18.7.14", | ||
| "@types/prompts": "^2.0.14", | ||
| "@types/validate-npm-package-name": "^4.0.0", | ||
| "@vercel/ncc": "^0.34.0", | ||
| "aws-cdk-lib": "^2.40.0", | ||
| "chalk": "^5.0.1", | ||
| "commander": "^9.4.0", | ||
| "cross-spawn": "^7.0.3", | ||
| "functionless": "^0.22.6", | ||
| "mustache": "^4.2.0", | ||
| "prompts": "^2.4.2", | ||
| "rimraf": "^3.0.2", | ||
| "typescript": "^4.8.2", | ||
| "validate-npm-package-name": "^4.0.0" | ||
| }, | ||
| "bin": { | ||
| "create-functionless": "./dist/index.js" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| #!/usr/bin/env node | ||
| import chalk from "chalk"; | ||
| import { Command } from "commander"; | ||
| import spawn from "cross-spawn"; | ||
| import fs from "fs"; | ||
| import mustache from "mustache"; | ||
| import path from "path"; | ||
| import prompts from "prompts"; | ||
| import validateProjectName from "validate-npm-package-name"; | ||
| import packageJson from "../package.json"; | ||
|
|
||
| const program = new Command(); | ||
|
|
||
| program.name(packageJson.name).version(packageJson.version).parse(process.argv); | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| async function askProjectName() { | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const defaultName = "new-project"; | ||
|
|
||
| const answer = await prompts({ | ||
| type: "text", | ||
| name: "projectName", | ||
| message: "Project name:", | ||
| initial: defaultName, | ||
| validate: (name) => { | ||
| const result = validateProjectName(name); | ||
| if (result.validForNewPackages) return true; | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return `Invalid project name: ${name}`; | ||
| }, | ||
| }); | ||
|
|
||
| if (typeof answer.projectName === "string") { | ||
| return answer.projectName.trim(); | ||
| } | ||
|
|
||
| return defaultName; | ||
| } | ||
|
|
||
| function failOnError(response: ReturnType<typeof spawn.sync>, message: string) { | ||
| if (response.status !== 0) { | ||
| console.error(chalk.red(message)); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| async function run() { | ||
| const templateName = "default"; | ||
| const templateRoot = path.join(__dirname, "..", "templates", templateName); | ||
| const templateManifestPath = path.join(templateRoot, "manifest.json"); | ||
| const templateManifest: string[] = JSON.parse( | ||
| await fs.promises.readFile(templateManifestPath, "utf-8") | ||
| ); | ||
|
|
||
| const projectName = await askProjectName(); | ||
|
|
||
| console.log(); | ||
| console.log(`Creating ${chalk.green(projectName)}...`); | ||
|
|
||
| const root = path.resolve(projectName); | ||
|
|
||
| try { | ||
| await fs.promises.mkdir(root); | ||
| } catch (err: any) { | ||
| if (err.code === "EEXIST") { | ||
sam-goodwin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| console.error(`${chalk.red(`Folder already exists: ${projectName}`)}`); | ||
| } | ||
| process.exit(1); | ||
| } | ||
|
|
||
| const renderTemplate = async ( | ||
| localPath: string, | ||
| data: Record<string, unknown> | ||
| ) => { | ||
| const templateFilePath = path.join(templateRoot, localPath); | ||
| const templateContent = mustache.render( | ||
| await fs.promises.readFile(templateFilePath, "utf-8"), | ||
| data | ||
| ); | ||
| // Npm won't include `.gitignore` files in a package. | ||
| // This allows you to add .template as a file ending | ||
| // and it will be removed when rendered in the end | ||
| // project. | ||
|
Comment on lines
+74
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand what you mean by this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Take a look at https://github.com/functionless/create-functionless/pull/1/files#diff-b3dcca123bc557a15a933374361c741e8f04f515436c7aaa8f9fa89618f6c4c8 If I were to keep the name as |
||
| const destinationPath = path.join(root, localPath.replace(".template", "")); | ||
| await fs.promises.mkdir(path.dirname(destinationPath), { | ||
| recursive: true, | ||
| }); | ||
| await fs.promises.writeFile(destinationPath, templateContent); | ||
| }; | ||
|
|
||
| for (const path of templateManifest) { | ||
| await renderTemplate(path, { | ||
| projectName, | ||
| }); | ||
| } | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| process.chdir(root); | ||
|
|
||
| console.log(); | ||
| console.log("Installing packages..."); | ||
| console.log(); | ||
|
Comment on lines
+95
to
+97
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: provide a helper or use |
||
|
|
||
| const dependencies = [ | ||
| "typescript", | ||
| "functionless", | ||
| "@functionless/ast-reflection", | ||
| "@functionless/language-service", | ||
| "aws-sdk", | ||
| "typesafe-dynamodb", | ||
| "aws-cdk", | ||
| "aws-cdk-lib", | ||
| "@aws-cdk/aws-appsync-alpha", | ||
| "constructs", | ||
| "esbuild", | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ]; | ||
tvanhens marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| failOnError( | ||
| spawn.sync("yarn", ["add", "-D", ...dependencies], { | ||
| stdio: "inherit", | ||
| }), | ||
| "Unable to install dependencies" | ||
| ); | ||
|
|
||
| console.log(); | ||
| console.log("Initializing git repository..."); | ||
| console.log(); | ||
|
|
||
| const gitErrorMessage = "Error initializing git repository."; | ||
|
|
||
| failOnError( | ||
| spawn.sync("git", ["init", "-q"], { | ||
tvanhens marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| stdio: "inherit", | ||
| }), | ||
| gitErrorMessage | ||
| ); | ||
|
|
||
| failOnError( | ||
| spawn.sync("git", ["add", "."], { | ||
| stdio: "inherit", | ||
| }), | ||
| gitErrorMessage | ||
| ); | ||
|
|
||
| failOnError( | ||
| spawn.sync("git", ["commit", "-q", "-m", "initial commit"], { | ||
| stdio: "inherit", | ||
| }), | ||
| gitErrorMessage | ||
| ); | ||
|
|
||
| console.log(chalk.green("Project ready!")); | ||
| console.log(); | ||
| console.log(`Run ${chalk.yellow(`cd ./${projectName}`)} to get started.`); | ||
|
|
||
| process.exit(0); | ||
| } | ||
|
|
||
| run(); | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| .swc/ | ||
| cdk.out/ | ||
| node_modules/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| { | ||
| "jsc": { | ||
| "parser": { | ||
| "syntax": "typescript", | ||
| "dynamicImport": false, | ||
| "decorators": false, | ||
| "hidden": { | ||
| "jest": true | ||
| } | ||
| }, | ||
| "transform": null, | ||
| "target": "es2021", | ||
| "loose": false, | ||
| "externalHelpers": false, | ||
| "experimental": { | ||
| "plugins": [["@functionless/ast-reflection", {}]] | ||
| } | ||
| }, | ||
| "minify": false, | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "sourceMaps": "inline", | ||
| "module": { | ||
| "type": "commonjs" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "app": "node -r '@swc/register' ./src/app.ts" | ||
tvanhens marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| [ | ||
| "package.json", | ||
| "cdk.json", | ||
| "tsconfig.json", | ||
| ".swcrc", | ||
| ".gitignore.template", | ||
| "src/app.ts" | ||
| ] | ||
tvanhens marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "name": "{{projectName}}", | ||
| "version": "0.1.0", | ||
| "private": true, | ||
| "scripts": { | ||
| "deploy": "cdk deploy", | ||
| "synth": "cdk synth" | ||
| }, | ||
tvanhens marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "devDependencies": {} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { App, Stack } from "aws-cdk-lib"; | ||
| import { Function, StepFunction } from "functionless"; | ||
|
|
||
| const app = new App(); | ||
|
|
||
| const stack = new Stack(app, "MyStack"); | ||
|
|
||
| const sayFunction = new Function( | ||
| stack, | ||
| "SayFunction", | ||
| async (event: { message: string }) => { | ||
| console.log(event.message); | ||
| } | ||
| ); | ||
|
|
||
| new StepFunction(stack, "Workflow", async (event: { name: string }) => { | ||
| sayFunction({ message: `Hello ${event.name}` }); | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| { | ||
| "compilerOptions": { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this all we want?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure. I used the defaults |
||
| "target": "es2016", | ||
tvanhens marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| "module": "commonjs", | ||
| "esModuleInterop": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "strict": true, | ||
| "skipLibCheck": true, | ||
| "plugins": [ | ||
| { | ||
| "name": "@functionless/language-service" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "compilerOptions": { | ||
| "target": "es2019", | ||
| "moduleResolution": "node", | ||
| "resolveJsonModule": true, | ||
| "esModuleInterop": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "strict": true, | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reasoning around this over 0.0.0? I don't have strong opinions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
semantic release will use
1.0.xas the current version if you specify0.0.0. There's probably a way to override that with config but using0.1.0as the base seemed like a reasonable trade off.