├── .prettierrc
├── .husky
└── pre-commit
├── docs
├── src
│ ├── pages
│ │ ├── cli
│ │ │ ├── create.mdx
│ │ │ ├── _meta.json
│ │ │ └── intro.mdx
│ │ ├── core
│ │ │ ├── _meta.json
│ │ │ └── intro.mdx
│ │ ├── ui
│ │ │ ├── _meta.json
│ │ │ └── intro.mdx
│ │ ├── infra
│ │ │ ├── _meta.json
│ │ │ ├── intro.mdx
│ │ │ └── tips.mdx
│ │ ├── index.mdx
│ │ ├── overview
│ │ │ ├── guides
│ │ │ │ └── _meta.json
│ │ │ ├── contributors
│ │ │ │ ├── tips.mdx
│ │ │ │ ├── _meta.json
│ │ │ │ ├── resources.mdx
│ │ │ │ ├── intro.mdx
│ │ │ │ └── fix-audit-issues.mdx
│ │ │ ├── _meta.json
│ │ │ ├── common-error-resolutions.mdx
│ │ │ ├── quick-start.mdx
│ │ │ ├── packages.mdx
│ │ │ └── faq.mdx
│ │ ├── _app.mdx
│ │ ├── learn
│ │ │ ├── _meta.json
│ │ │ └── resources.mdx
│ │ └── _meta.json
│ ├── globals.css
│ └── components
│ │ ├── utils.ts
│ │ ├── Link.tsx
│ │ └── Feature.tsx
├── public
│ ├── og2.png
│ ├── fast-forward-emoji.svg
│ ├── green-boost-gradient.svg
│ └── fast-forward-gradient.svg
├── postcss.config.cjs
├── CHANGELOG.md
├── IDEAS.md
├── tailwind.config.js
├── .lintstagedrc.js
├── tsconfig.json
├── .gitignore
├── next.config.js
└── package.json
├── examples
├── widgets-dynamo
│ ├── ui
│ │ ├── .gitignore
│ │ ├── vite-env.d.ts
│ │ ├── tsconfig.json
│ │ ├── src
│ │ │ ├── components
│ │ │ │ ├── NavAsideLink.css.ts
│ │ │ │ ├── Footer.tsx
│ │ │ │ ├── NavAsideLink.tsx
│ │ │ │ ├── Header.tsx
│ │ │ │ └── NavAside.tsx
│ │ │ ├── pages
│ │ │ │ ├── Root.tsx
│ │ │ │ └── widgets
│ │ │ │ │ └── WidgetsAdditionalActions.tsx
│ │ │ ├── config.ts
│ │ │ ├── utils
│ │ │ │ ├── date.ts
│ │ │ │ └── format.ts
│ │ │ ├── main.tsx
│ │ │ ├── theme.ts
│ │ │ ├── trpc.ts
│ │ │ └── App.css.ts
│ │ ├── public
│ │ │ ├── browserconfig.xml
│ │ │ ├── site.webmanifest
│ │ │ ├── og-icon.svg
│ │ │ ├── favicon-16x16.png
│ │ │ ├── safari-pinned-tab.svg
│ │ │ ├── favicon-32x32.png
│ │ │ ├── mstile-144x144.png
│ │ │ ├── mstile-70x70.png
│ │ │ └── android-chrome-192x192.png
│ │ ├── .lintstagedrc.js.t
│ │ ├── .eslintrc.cjs
│ │ └── index.html
│ ├── .gitignore
│ ├── db
│ │ ├── src
│ │ │ ├── config.ts
│ │ │ └── README.md
│ │ ├── tsconfig.json
│ │ ├── README.md
│ │ ├── .lintstagedrc.js.t
│ │ ├── .eslintrc.cjs
│ │ └── package.json
│ ├── core
│ │ ├── src
│ │ │ ├── README.md
│ │ │ ├── index.ts
│ │ │ ├── domain
│ │ │ │ ├── models
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── base.ts
│ │ │ │ │ ├── widget-component.ts
│ │ │ │ │ ├── component.ts
│ │ │ │ │ └── widget.ts
│ │ │ │ └── schemas
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── common.ts
│ │ │ ├── config.ts
│ │ │ ├── entrypoints
│ │ │ │ └── api
│ │ │ │ │ ├── trpc.ts
│ │ │ │ │ ├── router.ts
│ │ │ │ │ ├── handler.ts
│ │ │ │ │ └── routers
│ │ │ │ │ ├── widget.ts
│ │ │ │ │ └── components.ts
│ │ │ ├── utils
│ │ │ │ └── logger.ts
│ │ │ ├── stage-name.ts
│ │ │ └── services
│ │ │ │ ├── widget-service.ts
│ │ │ │ └── component-service.ts
│ │ ├── tsconfig.json
│ │ ├── .lintstagedrc.js.t
│ │ └── .eslintrc.cjs
│ ├── infra
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── vite.config.ts
│ │ ├── tsconfig.json
│ │ ├── src
│ │ │ ├── pipeline
│ │ │ │ └── pipeline-app.ts
│ │ │ ├── local-app.ts
│ │ │ └── app
│ │ │ │ └── stateless
│ │ │ │ └── monitor.ts
│ │ ├── .lintstagedrc.js.t
│ │ ├── .eslintrc.cjs
│ │ └── cdk.json
│ ├── pnpm-workspace.yaml
│ ├── packages
│ │ ├── tsconfig
│ │ │ ├── tsconfig.ui.json
│ │ │ ├── tsconfig.node.json
│ │ │ └── package.json
│ │ ├── utils
│ │ │ ├── package.json
│ │ │ └── index.js
│ │ ├── eslint-config-react
│ │ │ ├── package.json
│ │ │ └── .eslintrc.cjs
│ │ └── eslint-config-node
│ │ │ ├── package.json
│ │ │ └── .eslintrc.cjs
│ ├── .vscode
│ │ └── settings.json
│ └── package.json
├── document-management
│ └── README.md
├── cloud-broker
│ └── README.md
└── README.md
├── packages
├── gboost
│ ├── templates
│ │ ├── minimal
│ │ │ ├── core
│ │ │ │ ├── src
│ │ │ │ │ ├── index.shared.ts
│ │ │ │ │ └── index.shared.test.ts
│ │ │ │ ├── tsconfig.json.t
│ │ │ │ ├── .lintstagedrc.js.t
│ │ │ │ ├── .eslintrc.cjs.t
│ │ │ │ └── package.json.t
│ │ │ ├── ui
│ │ │ │ ├── .env.t
│ │ │ │ ├── src
│ │ │ │ │ └── app
│ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ ├── page.test.tsx
│ │ │ │ │ │ ├── favicon.ico
│ │ │ │ │ │ └── apple-touch-icon.png
│ │ │ │ ├── next-env.d.ts.t
│ │ │ │ ├── .eslintrc.cjs.t
│ │ │ │ ├── tsconfig.json.t
│ │ │ │ ├── .lintstagedrc.js.t
│ │ │ │ ├── .gitignore
│ │ │ │ ├── package.json.t
│ │ │ │ └── next.config.js
│ │ │ ├── .gitignore.t
│ │ │ ├── infra
│ │ │ │ ├── .gitignore
│ │ │ │ ├── src
│ │ │ │ │ ├── app-stage.test.ts
│ │ │ │ │ └── app-stage.ts
│ │ │ │ ├── tsconfig.json.t
│ │ │ │ ├── .lintstagedrc.js.t
│ │ │ │ ├── .eslintrc.cjs.t
│ │ │ │ └── package.json.t
│ │ │ ├── .husky
│ │ │ │ └── pre-commit
│ │ │ ├── pnpm-workspace.yaml
│ │ │ ├── packages
│ │ │ │ ├── tsconfig
│ │ │ │ │ ├── tsconfig.node.json.t
│ │ │ │ │ ├── tsconfig.next.json.t
│ │ │ │ │ └── package.json.t
│ │ │ │ ├── utils
│ │ │ │ │ ├── package.json.t
│ │ │ │ │ └── index.js
│ │ │ │ ├── eslint-config-next
│ │ │ │ │ └── package.json.t
│ │ │ │ └── eslint-config-node
│ │ │ │ │ ├── package.json.t
│ │ │ │ │ └── .eslintrc.cjs.t
│ │ │ ├── .vscode
│ │ │ │ └── settings.json
│ │ │ ├── README.md
│ │ │ └── package.json.t
│ │ ├── basic-ui
│ │ │ ├── core
│ │ │ │ └── src
│ │ │ │ │ ├── index.server.ts
│ │ │ │ │ ├── index.shared.ts
│ │ │ │ │ └── config
│ │ │ │ │ ├── stage-name.ts
│ │ │ │ │ ├── server-config.ts
│ │ │ │ │ └── shared-config.ts
│ │ │ ├── ui
│ │ │ │ └── src
│ │ │ │ │ ├── app
│ │ │ │ │ ├── globals.css
│ │ │ │ │ ├── hello
│ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ └── [name]
│ │ │ │ │ │ │ ├── loading.tsx
│ │ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ │ └── Hello.tsx
│ │ │ │ │ ├── page.tsx
│ │ │ │ │ ├── goodbye
│ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ └── [name]
│ │ │ │ │ │ │ ├── loading.tsx
│ │ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ │ └── Goodbye.tsx
│ │ │ │ │ └── layout.tsx
│ │ │ │ │ ├── utils
│ │ │ │ │ ├── kebab-to-title.ts
│ │ │ │ │ └── kebab-to-title.test.ts
│ │ │ │ │ ├── config
│ │ │ │ │ ├── server-config.ts
│ │ │ │ │ └── client-config.ts
│ │ │ │ │ ├── components
│ │ │ │ │ ├── LoadingH2.tsx
│ │ │ │ │ ├── layout
│ │ │ │ │ │ ├── Footer.tsx
│ │ │ │ │ │ ├── DrawerList.tsx
│ │ │ │ │ │ └── Drawer.tsx
│ │ │ │ │ └── theme
│ │ │ │ │ │ ├── ThemeRegistry.tsx
│ │ │ │ │ │ └── theme.tsx
│ │ │ │ │ └── core-server.ts
│ │ │ └── infra
│ │ │ │ └── src
│ │ │ │ ├── local-app.ts
│ │ │ │ ├── pipeline
│ │ │ │ └── pipeline-app.ts
│ │ │ │ ├── app
│ │ │ │ └── stateless
│ │ │ │ │ └── waf-stack.ts
│ │ │ │ └── app-stage.ts
│ │ ├── crud-core
│ │ │ ├── core
│ │ │ │ ├── src
│ │ │ │ │ ├── types
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── search-params.ts
│ │ │ │ │ ├── modules
│ │ │ │ │ │ ├── base
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── base.entity.ts
│ │ │ │ │ │ │ └── base.schema.ts
│ │ │ │ │ │ └── item
│ │ │ │ │ │ │ ├── index.shared.ts
│ │ │ │ │ │ │ ├── delete-item.use-case.ts
│ │ │ │ │ │ │ ├── create-item.use-case.ts
│ │ │ │ │ │ │ ├── get-item.use-case.ts
│ │ │ │ │ │ │ ├── update-item.use-case.ts
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── item.entity.ts
│ │ │ │ │ │ │ └── list-items.use-case.ts
│ │ │ │ │ ├── adapters
│ │ │ │ │ │ └── secondary
│ │ │ │ │ │ │ └── logger-adapter.ts
│ │ │ │ │ ├── config
│ │ │ │ │ │ ├── stage-name.ts
│ │ │ │ │ │ └── shared-config.ts
│ │ │ │ │ ├── index.server.ts
│ │ │ │ │ └── index.shared.ts
│ │ │ │ └── tsconfig.json.t
│ │ │ ├── ui
│ │ │ │ ├── src
│ │ │ │ │ ├── app
│ │ │ │ │ │ ├── page.test.tsx
│ │ │ │ │ │ ├── globals.css
│ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ ├── items
│ │ │ │ │ │ │ ├── new
│ │ │ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ │ │ └── create-item.action.ts
│ │ │ │ │ │ │ ├── [id]
│ │ │ │ │ │ │ │ ├── update-item.action.ts
│ │ │ │ │ │ │ │ └── page.tsx
│ │ │ │ │ │ │ ├── page.tsx
│ │ │ │ │ │ │ └── ItemsToolbar.tsx
│ │ │ │ │ │ └── layout.tsx
│ │ │ │ │ ├── utils
│ │ │ │ │ │ ├── format.ts
│ │ │ │ │ │ ├── decode-search-params.ts
│ │ │ │ │ │ └── generate-csp.ts
│ │ │ │ │ ├── config
│ │ │ │ │ │ ├── server-config.ts
│ │ │ │ │ │ └── client-config.ts
│ │ │ │ │ ├── types
│ │ │ │ │ │ └── page-props.ts
│ │ │ │ │ ├── components
│ │ │ │ │ │ ├── layout
│ │ │ │ │ │ │ ├── Footer.tsx
│ │ │ │ │ │ │ ├── DrawerList.tsx
│ │ │ │ │ │ │ └── Drawer.tsx
│ │ │ │ │ │ ├── theme
│ │ │ │ │ │ │ ├── ThemeRegistry.tsx
│ │ │ │ │ │ │ └── theme.tsx
│ │ │ │ │ │ └── rhf-inputs
│ │ │ │ │ │ │ └── RhfTextField.tsx
│ │ │ │ │ ├── core-server.ts
│ │ │ │ │ └── middleware.ts
│ │ │ │ ├── .eslintrc.cjs.t
│ │ │ │ └── package.json.t
│ │ │ └── infra
│ │ │ │ └── src
│ │ │ │ ├── local-app.ts
│ │ │ │ ├── pipeline
│ │ │ │ └── pipeline-app.ts
│ │ │ │ └── app
│ │ │ │ └── stateless
│ │ │ │ └── waf-stack.ts
│ │ ├── crud-postgres
│ │ │ ├── core
│ │ │ │ ├── src
│ │ │ │ │ ├── db
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── drizzle
│ │ │ │ │ │ │ ├── 0002_calm_mandarin.sql
│ │ │ │ │ │ │ ├── 0001_loud_serpent_society.sql
│ │ │ │ │ │ │ ├── meta
│ │ │ │ │ │ │ │ ├── 0000_snapshot.json
│ │ │ │ │ │ │ │ └── _journal.json
│ │ │ │ │ │ │ └── 0000_boring_maginty.sql
│ │ │ │ │ │ ├── drizzle.config.ts
│ │ │ │ │ │ ├── schema.ts
│ │ │ │ │ │ ├── scripts
│ │ │ │ │ │ │ └── seed-items.ts
│ │ │ │ │ │ └── utils
│ │ │ │ │ │ │ ├── get-db-auth-token.ts
│ │ │ │ │ │ │ └── get-db-password.ts
│ │ │ │ │ ├── adapters
│ │ │ │ │ │ └── secondary
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ └── db-adapter.ts
│ │ │ │ │ ├── modules
│ │ │ │ │ │ └── item
│ │ │ │ │ │ │ └── item.db.ts
│ │ │ │ │ ├── config
│ │ │ │ │ │ └── server-config.ts
│ │ │ │ │ └── utils
│ │ │ │ │ │ └── transform-null-to-undefined.ts
│ │ │ │ └── tsconfig.json.t
│ │ │ ├── .envrc
│ │ │ ├── infra
│ │ │ │ └── src
│ │ │ │ │ └── utils
│ │ │ │ │ ├── get-db-fn-props.ts
│ │ │ │ │ └── connect-fn-to-db.ts
│ │ │ └── README.md
│ │ └── crud-dynamo
│ │ │ ├── README.md
│ │ │ └── core
│ │ │ └── package.json.t
│ ├── src
│ │ ├── create
│ │ │ ├── ask.test.ts
│ │ │ ├── get-template-operations
│ │ │ │ ├── base-operation-params.ts
│ │ │ │ ├── get-minimal-operations.ts
│ │ │ │ ├── get-crud-dynamo-operations.ts
│ │ │ │ └── get-basic-ui-operations.ts
│ │ │ ├── operations
│ │ │ │ ├── operations.ts
│ │ │ │ ├── common.ts
│ │ │ │ ├── rename-files.ts
│ │ │ │ └── rename-files.test.ts
│ │ │ └── execute-operations.ts
│ │ ├── utils
│ │ │ └── handle-aborted.ts
│ │ └── invoke
│ │ │ └── inject-fn-config.ts
│ ├── tsconfig.build.json
│ ├── .lintstagedrc.js
│ ├── tsconfig.json
│ ├── scripts
│ │ └── build.ts
│ └── README.md
├── gboost-node
│ ├── src
│ │ ├── index.ts
│ │ └── index.test.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ ├── .lintstagedrc.js
│ ├── scripts
│ │ └── build.ts
│ ├── README.md
│ └── package.json
├── gboost-ui
│ ├── src
│ │ ├── utils
│ │ │ ├── index.ts
│ │ │ ├── use-trace-update.test.ts
│ │ │ ├── download-link.ts
│ │ │ └── use-trace-update.ts
│ │ ├── index.ts
│ │ └── types
│ │ │ └── string-with-autocomplete.ts
│ ├── tsconfig.build.json
│ ├── .lintstagedrc.js
│ ├── README.md
│ └── tsconfig.json
├── gboost-infra
│ ├── src
│ │ ├── user-base
│ │ │ ├── index.ts
│ │ │ ├── pre-token-generation.ts
│ │ │ └── post-confirmation.ts
│ │ ├── aspects
│ │ │ ├── index.ts
│ │ │ ├── suppress-nags
│ │ │ │ ├── suppress-cdk-custom-resource.ts
│ │ │ │ ├── suppress-cdk-log-retention.ts
│ │ │ │ ├── suppress-cdk-bucket-notifications.ts
│ │ │ │ ├── suppress-cdk-bucket-deployment.ts
│ │ │ │ ├── suppress-cdk-custom-resource-provider.ts
│ │ │ │ └── suppress-cdk-monitoring-constructs.ts
│ │ │ └── gov-cloud-compat.ts
│ │ ├── web-deployment
│ │ │ └── common.ts
│ │ ├── user-management
│ │ │ ├── function
│ │ │ │ ├── validateUsernames.ts
│ │ │ │ ├── getCognitoIdentity.ts
│ │ │ │ ├── deleteUsers.ts
│ │ │ │ ├── enableUsers.ts
│ │ │ │ ├── disableUsers.ts
│ │ │ │ └── resetPasswords.ts
│ │ │ └── includeSelectionSetList.vtl
│ │ ├── file-upload
│ │ │ └── function
│ │ │ │ └── findIndex.ts
│ │ ├── static-site
│ │ │ ├── rewrite-url.js
│ │ │ └── response-headers.test.ts
│ │ ├── table.ts
│ │ ├── construct-default-props.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ ├── .lintstagedrc.js
│ ├── tsconfig.build.json
│ └── README.md
└── gboost-common
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ ├── .lintstagedrc.js
│ ├── src
│ ├── convert-case.test.ts
│ ├── index.ts
│ ├── convert-case.ts
│ ├── merge-deep.ts
│ └── get-error-message.ts
│ ├── scripts
│ └── build.ts
│ └── README.md
├── .gitignore
├── NOTICE
├── .changeset
├── pretty-flies-smell.md
├── config.json
├── README.md
└── neat-waves-impress.md
├── .vscode
├── extensions.json
├── settings.json
└── launch.json
├── tsconfig.json
├── pnpm-workspace.yaml
├── CODE_OF_CONDUCT.md
├── README.md
└── .github
├── actions
└── install
│ └── action.yml
└── workflows
└── pages-deploy.yml
/.prettierrc:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | pnpm lint-staged
2 |
--------------------------------------------------------------------------------
/docs/src/pages/cli/create.mdx:
--------------------------------------------------------------------------------
1 | # `gboost create`
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | *.local
3 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/core/src/index.shared.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_STORE
--------------------------------------------------------------------------------
/docs/src/pages/cli/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Introduction"
3 | }
--------------------------------------------------------------------------------
/docs/src/pages/core/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Introduction"
3 | }
--------------------------------------------------------------------------------
/docs/src/pages/ui/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Introduction"
3 | }
--------------------------------------------------------------------------------
/packages/gboost-node/src/index.ts:
--------------------------------------------------------------------------------
1 | export const hello = "world";
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | dist
4 | .env
5 | *.tsbuildinfo
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
--------------------------------------------------------------------------------
/examples/document-management/README.md:
--------------------------------------------------------------------------------
1 | # Document Management
2 |
3 | TODO
--------------------------------------------------------------------------------
/examples/widgets-dynamo/db/src/config.ts:
--------------------------------------------------------------------------------
1 | export const config = {};
2 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/.env.t:
--------------------------------------------------------------------------------
1 | NEXT_PUBLIC_STAGE_NAME=local
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/README.md:
--------------------------------------------------------------------------------
1 | # Core
2 | Add backend logic here
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./stage-name.js";
2 |
--------------------------------------------------------------------------------
/packages/gboost-ui/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./download-link.js";
2 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/packages/gboost-ui/src/index.ts:
--------------------------------------------------------------------------------
1 | export { downloadLink } from "./utils/index";
2 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/.gitignore.t:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_STORE
3 | .envrc
--------------------------------------------------------------------------------
/docs/src/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/docs/public/og2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awslabs/green-boost/HEAD/docs/public/og2.png
--------------------------------------------------------------------------------
/docs/src/pages/cli/intro.mdx:
--------------------------------------------------------------------------------
1 | # CLI Introduction
2 |
3 | Welcome to the docs for `gboost`.
--------------------------------------------------------------------------------
/docs/src/pages/infra/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Introduction",
3 | "tips": "Tips"
4 | }
--------------------------------------------------------------------------------
/docs/src/pages/ui/intro.mdx:
--------------------------------------------------------------------------------
1 | # UI Introduction
2 |
3 | Welcome to the docs for `gboost-ui`.
--------------------------------------------------------------------------------
/docs/src/pages/core/intro.mdx:
--------------------------------------------------------------------------------
1 | # Core Introduction
2 |
3 | Welcome to the docs for `gboost-node`.
--------------------------------------------------------------------------------
/docs/src/pages/index.mdx:
--------------------------------------------------------------------------------
1 | import { Landing } from "../components/Landing";
2 |
3 |
4 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/db/src/README.md:
--------------------------------------------------------------------------------
1 | # DB
2 | Add database scripts and utility functions here.
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/.gitignore:
--------------------------------------------------------------------------------
1 | # CDK asset staging directory
2 | .cdk.staging
3 | cdk.out
--------------------------------------------------------------------------------
/docs/src/pages/infra/intro.mdx:
--------------------------------------------------------------------------------
1 | # Infra Introduction
2 |
3 | Welcome to the docs for `gboost-infra`.
--------------------------------------------------------------------------------
/packages/gboost-node/src/index.test.ts:
--------------------------------------------------------------------------------
1 | import { test } from "vitest";
2 |
3 | test.todo("TODO");
4 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/db/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@myapp/tsconfig/tsconfig.node.json",
3 | }
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/infra/.gitignore:
--------------------------------------------------------------------------------
1 | # CDK asset staging directory
2 | .cdk.staging
3 | cdk.out
--------------------------------------------------------------------------------
/docs/src/components/utils.ts:
--------------------------------------------------------------------------------
1 | export const gradientClasses = "bg-gradient-to-r from-lime-400 to-cyan-400";
2 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@myapp/tsconfig/tsconfig.node.json",
3 | }
4 |
--------------------------------------------------------------------------------
/.changeset/pretty-flies-smell.md:
--------------------------------------------------------------------------------
1 | ---
2 | "gboost": patch
3 | ---
4 |
5 | infra: cdk destroy command correction
6 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/core/src/index.server.ts:
--------------------------------------------------------------------------------
1 | export { ServerConfig } from "./config/server-config";
2 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type { SearchParams } from "./search-params";
2 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/index.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | export { schema } from "./schema";
3 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | export default function Page() {
2 | return <>>;
3 | }
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | pnpm lint-staged
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/domain/models/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./widget.js";
2 | export * from "./component.js";
3 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/src/app/page.test.tsx:
--------------------------------------------------------------------------------
1 | import { test } from "vitest";
2 |
3 | test.todo("write tests");
4 |
--------------------------------------------------------------------------------
/docs/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/tsconfig.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@{{GB_APP_ID}}/tsconfig/tsconfig.node.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/app/page.test.tsx:
--------------------------------------------------------------------------------
1 | import { test } from "vitest";
2 |
3 | test.todo("write tests");
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/core/src/index.shared.test.ts:
--------------------------------------------------------------------------------
1 | import { test } from "vitest";
2 |
3 | test.todo("write tests");
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/core/tsconfig.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@{{GB_APP_ID}}/tsconfig/tsconfig.node.json",
3 | }
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/infra/src/app-stage.test.ts:
--------------------------------------------------------------------------------
1 | import { test } from "vitest";
2 |
3 | test.todo("write tests");
4 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/config.ts:
--------------------------------------------------------------------------------
1 | export const config = {
2 | widgetsTableName: process.env["WIDGETS_TABLE_NAME"],
3 | };
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/globals.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --app-bar-height: 60px;
3 | --drawer-width: 240px;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/app/globals.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --app-bar-height: 60px;
3 | --drawer-width: 240px;
4 | }
5 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/domain/schemas/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./widget-schemas.js";
2 | export * from "./component-schemas.js";
3 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/user-base/index.ts:
--------------------------------------------------------------------------------
1 | export {} from "./oidc-user-base";
2 | export { type UserBaseProps } from "./user-base.js";
3 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/entrypoints/api/trpc.ts:
--------------------------------------------------------------------------------
1 | import { initTRPC } from "@trpc/server";
2 |
3 | export const t = initTRPC.create();
4 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/README.md:
--------------------------------------------------------------------------------
1 | # /infra
2 |
3 | /infra is where you define your infrastructure with the AWS Cloud Development Kit (CDK)
--------------------------------------------------------------------------------
/docs/public/fast-forward-emoji.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/src/pages/overview/guides/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "aws-credentials": "AWS Credentials",
3 | "clean-code": "Clean Code",
4 | "config": "Configuration"
5 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/base/index.ts:
--------------------------------------------------------------------------------
1 | export { BaseEntity } from "./base.entity";
2 | export { baseSchema } from "./base.schema";
3 |
--------------------------------------------------------------------------------
/docs/src/pages/_app.mdx:
--------------------------------------------------------------------------------
1 | import "../globals.css";
2 |
3 | export default function App({ Component, pageProps }) {
4 | return ;
5 | }
6 |
--------------------------------------------------------------------------------
/docs/src/pages/infra/tips.mdx:
--------------------------------------------------------------------------------
1 | # Tips
2 |
3 | - Don't define all your infrastructure within class constructors, use methods to make your constructs easier to follow.
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@myapp/tsconfig/tsconfig.ui.json",
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awslabs/green-boost/HEAD/packages/gboost/templates/minimal/ui/src/app/favicon.ico
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "esbenp.prettier-vscode",
5 | "usernamehw.errorlens"
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/core/src/index.shared.ts:
--------------------------------------------------------------------------------
1 | export { SharedConfig } from "./config/shared-config";
2 | export { StageName } from "./config/stage-name";
3 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | export function formatDate(date?: string) {
2 | return date ? new Date(date).toLocaleString() : "";
3 | }
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/drizzle/0002_calm_mandarin.sql:
--------------------------------------------------------------------------------
1 | ALTER TABLE "{{GB_SQL_APP_ID}}"."item" ALTER COLUMN "id" SET DEFAULT gen_random_uuid();
--------------------------------------------------------------------------------
/docs/src/pages/overview/contributors/tips.mdx:
--------------------------------------------------------------------------------
1 | # Tips
2 |
3 | ## JavaScript
4 |
5 | - Avoid `export * from "./some-file"`. It makes tracking down imported functions/classes difficult.
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/src/app/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awslabs/green-boost/HEAD/packages/gboost/templates/minimal/ui/src/app/apple-touch-icon.png
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/types/search-params.ts:
--------------------------------------------------------------------------------
1 | type SearchParamValues = string | string[] | undefined;
2 | export type SearchParams = Record;
3 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | export default defineConfig({
3 | resolve: {
4 | dedupe: ["aws-cdk-lib", "cdk-nag"],
5 | },
6 | });
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/.envrc:
--------------------------------------------------------------------------------
1 | # export AWS_PROFILE={{GB_APP_ID}}
2 | # export AWS_REGION=TODO
3 | export DB_SECRET_ARN=TODO
4 | export DB_BASTION_ID=TODO
5 | export DB_ENDPOINT=TODO
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/adapters/secondary/index.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | export { dbWrite, dbRead } from "./db-adapter";
3 | export { logger } from "./logger-adapter";
4 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/node18"],
3 | "compilerOptions": {
4 | "noEmit": true,
5 | },
6 | "include": ["scripts/**/*", "utils/**/*"],
7 | }
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { redirect } from "next/navigation";
3 |
4 | export default async function Page() {
5 | redirect("/items");
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/hello/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { redirect } from "next/navigation";
3 |
4 | export default function Page() {
5 | redirect("/hello/world");
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { redirect } from "next/navigation";
3 |
4 | export default async function Page() {
5 | redirect("/hello/world");
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/app/items/new/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { CreateItem } from "./CreateItem";
3 |
4 | export default function Page() {
5 | return ;
6 | }
7 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | - 'core'
2 | - 'db'
3 | - 'infra'
4 | - 'packages/tsconfig'
5 | - 'packages/eslint-config-node'
6 | - 'packages/eslint-config-react'
7 | - 'packages/utils'
8 | - 'ui'
--------------------------------------------------------------------------------
/packages/gboost/src/create/ask.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, test, expect } from "vitest";
2 |
3 | describe("ask.ts", () => {
4 | test("TODO", () => {
5 | expect("TODO").toEqual("TODO");
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/goodbye/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { redirect } from "next/navigation";
3 |
4 | export default function Page() {
5 | redirect("/goodbye/world");
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/tsconfig.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@{{GB_APP_ID}}/tsconfig/tsconfig.node.json",
3 | "compilerOptions": {
4 | "exactOptionalPropertyTypes": false
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/gboost'
3 | - 'packages/gboost-common'
4 | - 'packages/gboost-infra'
5 | - 'packages/gboost-node'
6 | - 'packages/gboost-ui'
7 | - 'docs'
8 | - 'docs/demos/**'
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@myapp/tsconfig/tsconfig.node.json",
3 | "exclude": ["cdk.out"],
4 | "compilerOptions": {
5 | "exactOptionalPropertyTypes": false
6 | },
7 | }
8 |
--------------------------------------------------------------------------------
/packages/gboost-ui/src/types/string-with-autocomplete.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @link https://twitter.com/diegohaz/status/1524257274012876801
3 | */
4 | export type StringWithAutocomplete = T | (string & Record);
5 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/tsconfig/tsconfig.ui.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/vite-react/tsconfig.json",
3 | "compilerOptions": {
4 | "module": "NodeNext",
5 | "moduleResolution": "NodeNext",
6 | },
7 | }
--------------------------------------------------------------------------------
/packages/gboost-node/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "noEmit": false,
5 | "outDir": "dist"
6 | },
7 | "exclude": ["src/**/*.test.ts", "scripts/**/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/gboost-ui/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "noEmit": false,
5 | "outDir": "dist"
6 | },
7 | "exclude": ["src/**/*.test.ts", "scripts/**/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/goodbye/[name]/loading.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { LoadingH2 } from "@/components/LoadingH2";
3 |
4 | export default function Loading() {
5 | return ;
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/hello/[name]/loading.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { LoadingH2 } from "@/components/LoadingH2";
3 |
4 | export default function Loading() {
5 | return ;
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost-common/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist",
5 | "noEmit": false
6 | },
7 | "exclude": ["src/**/*.test.ts", "scripts/**/*"]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/gboost/src/create/get-template-operations/base-operation-params.ts:
--------------------------------------------------------------------------------
1 | export interface BaseOperationParams {
2 | appId: string;
3 | appTitle: string;
4 | destinationPath: string;
5 | templatesDirPath: string;
6 | }
7 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/db/README.md:
--------------------------------------------------------------------------------
1 | # /db
2 |
3 | When building a web app, you often will need to seed or fill your database with sample data for demos or to tests various functionality. Use this workspace to create scripts to do that.
--------------------------------------------------------------------------------
/packages/gboost-infra/src/aspects/index.ts:
--------------------------------------------------------------------------------
1 | export { GovCloudCompat } from "./gov-cloud-compat.js";
2 | export { SuppressNags } from "./suppress-nags/suppress-nags.js";
3 | export { Suppression } from "./suppress-nags/suppression.js";
4 |
--------------------------------------------------------------------------------
/docs/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # gboost-docs
2 |
3 | ## 0.1.1
4 |
5 | ### Patch Changes
6 |
7 | - Updated dependencies [[`4680cc1`](https://github.com/awslabs/green-boost/commit/4680cc1e2290e5838f4b613980b48591683dbe99)]:
8 | - gboost-ui@0.36.0
9 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/utils/logger.ts:
--------------------------------------------------------------------------------
1 | import { Logger } from "@aws-lambda-powertools/logger";
2 |
3 | // Environment variable POWERTOOLS_SERVICE_NAME will determine service name of logger
4 | export const logger = new Logger();
5 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/index.shared.ts:
--------------------------------------------------------------------------------
1 | export {
2 | type ItemSchema,
3 | itemSchema,
4 | updateItemSchema,
5 | type ItemInputSchema,
6 | type UpdateItemInputSchema,
7 | } from "./item.schema";
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/infra/tsconfig.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@{{GB_APP_ID}}/tsconfig/tsconfig.node.json",
3 | "exclude": ["cdk.out"],
4 | "compilerOptions": {
5 | "exactOptionalPropertyTypes": false
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "core"
3 | - "infra"
4 | - "packages/eslint-config-next"
5 | - "packages/eslint-config-node"
6 | - "packages/tsconfig"
7 | - "packages/utils"
8 | - "ui"
9 |
--------------------------------------------------------------------------------
/docs/IDEAS.md:
--------------------------------------------------------------------------------
1 | # Ideas
2 |
3 | This is a scratch pad for future GB Docs ideas:
4 |
5 | - [] Add overview/guides/editor on which extensions to add: ESLint, Error Lens
6 | - [] Add overview/guides/debugging on how to use JavaScript Debug Terminal
--------------------------------------------------------------------------------
/packages/gboost-ui/src/utils/use-trace-update.test.ts:
--------------------------------------------------------------------------------
1 | import { expect, test } from "vitest";
2 | import { useTraceUpdate } from "./use-trace-update.js";
3 |
4 | test("use-trace-update", () => {
5 | expect(useTraceUpdate).toBeDefined();
6 | });
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/drizzle.config.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import type { Config } from "drizzle-kit";
3 |
4 | export default {
5 | out: `./src/db/drizzle`,
6 | schema: `./src/modules/**/*.db.ts`,
7 | } satisfies Config;
8 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/tsconfig/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/node18-strictest-esm/tsconfig.json",
3 | "compilerOptions": {
4 | "module": "NodeNext",
5 | "moduleResolution": "NodeNext",
6 | "noEmit": true,
7 | },
8 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/utils/kebab-to-title.ts:
--------------------------------------------------------------------------------
1 | export function kebabToTitle(value: string): string {
2 | const words = value
3 | .split("-")
4 | .map((w) => w.at(0)?.toUpperCase() + w.slice(1));
5 | return words.join(" ");
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/delete-item.use-case.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { itemRepo } from "./item.repo";
3 |
4 | export async function deleteItemUseCase(id: string): Promise {
5 | await itemRepo.remove(id);
6 | }
7 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/packages/tsconfig/tsconfig.node.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/node18"],
3 | "compilerOptions": {
4 | "module": "ESNext",
5 | "moduleResolution": "Bundler",
6 | "noEmit": true
7 | }
8 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@myapp/utils",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": {
6 | ".": "./index.js"
7 | },
8 | "dependencies": {
9 | "eslint": "^8.36.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/packages/tsconfig/tsconfig.next.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/next"],
3 | "compilerOptions": {
4 | "target": "ES2017",
5 | "module": "ESNext",
6 | "moduleResolution": "Bundler"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/next-env.d.ts.t:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/domain/models/base.ts:
--------------------------------------------------------------------------------
1 | export class Base {
2 | createdDate: string;
3 | updatedDate: string;
4 | constructor(params: Base) {
5 | this.createdDate = params.createdDate;
6 | this.updatedDate = params.updatedDate;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/docs/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | const config = {
3 | content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
4 | darkMode: "class",
5 | theme: {
6 | extend: {},
7 | },
8 | plugins: [],
9 | };
10 |
11 | export default config;
12 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/domain/schemas/common.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 |
3 | export const listSchema = z.object({
4 | cursor: z.string().optional(),
5 | pageSize: z.number().max(100).default(10),
6 | });
7 | export type ListSchema = z.infer;
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/packages/utils/package.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@{{GB_APP_ID}}/utils",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": {
6 | ".": "./index.js"
7 | },
8 | "dependencies": {
9 | "eslint": "^8.53.0"
10 | }
11 | }
--------------------------------------------------------------------------------
/examples/cloud-broker/README.md:
--------------------------------------------------------------------------------
1 | # Cloud Broker
2 |
3 | Cloud Broker is an example app built with Green Boost that gives organizations greater control over their AWS accounts. Cloud Broker provides a self-service platform with fine-grained access management and security controls.
4 |
5 | TODO
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/adapters/secondary/logger-adapter.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { Logger } from "@aws-lambda-powertools/logger";
3 |
4 | // Environment variable POWERTOOLS_SERVICE_NAME will determine service name of logger
5 | export const logger = new Logger();
6 |
--------------------------------------------------------------------------------
/packages/gboost-ui/src/utils/download-link.ts:
--------------------------------------------------------------------------------
1 | export async function downloadLink(link: string, fileName: string) {
2 | const element = document.createElement("a");
3 | element.href = link;
4 | element.download = fileName;
5 | document.body.appendChild(element);
6 | element.click();
7 | }
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/.eslintrc.cjs.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@{{GB_APP_ID}}/eslint-config-next"],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/components/NavAsideLink.css.ts:
--------------------------------------------------------------------------------
1 | import { style } from "@vanilla-extract/css";
2 |
3 | export const link = style({
4 | textDecoration: "none",
5 | });
6 |
7 | export const activeLink = style({
8 | backgroundColor: "var(--amplify-colors-neutral-40)",
9 | });
10 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.codeActionsOnSave": {
3 | "source.fixAll.eslint": true
4 | },
5 | "typescript.tsdk": "node_modules/typescript/lib",
6 | "search.exclude": {
7 | "**/node_modules": true,
8 | "**/cdk.out": true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/infra/src/app-stage.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { Stage } from "aws-cdk-lib";
3 | import type { Construct } from "constructs";
4 |
5 | export class AppStage extends Stage {
6 | constructor(scope: Construct, id: string) {
7 | super(scope, id);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/gboost-node/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/node18"],
3 | "compilerOptions": {
4 | "declaration": true,
5 | "declarationMap": true,
6 | "incremental": true,
7 | "noEmit": true
8 | },
9 | "include": ["src/**/*", "scripts/**/*"]
10 | }
11 |
--------------------------------------------------------------------------------
/docs/src/pages/overview/contributors/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Introduction",
3 | "testing-locally": "Testing Locally",
4 | "development-workflow": "Development Workflow",
5 | "dependencies": "Dependencies",
6 | "fix-audit-issues": "Fix Audit Issues",
7 | "resources": "Resources",
8 | "tips": "Tips"
9 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/stage-name.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Each stage name corresponds to stage. Local is for developer to deploy locally where all other stages are pipeline stages.
3 | */
4 | export enum StageName {
5 | Local = "local",
6 | Dev = "dev",
7 | Test = "test",
8 | Prod = "prod",
9 | }
10 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | import { ReactElement } from "react";
2 | import { View } from "@aws-amplify/ui-react";
3 |
4 | export function Footer(): ReactElement {
5 | return (
6 |
7 | Widgets App
8 |
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/docs/src/pages/overview/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Introduction",
3 | "prereqs": "Prerequisites",
4 | "quick-start": "Quick Start",
5 | "packages": "Packages",
6 | "guides": "Guides",
7 | "faq": "FAQ",
8 | "common-error-resolutions": "Common Error Resolutions",
9 | "contributors": "Contributors"
10 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/db/.lintstagedrc.js.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { removeIgnoredFiles } from "@myapp/utils";
3 |
4 | export default {
5 | "*.ts": async (files) => {
6 | const filesToLint = await removeIgnoredFiles(files);
7 | return [`eslint --fix --max-warnings=0 ${filesToLint}`, "tsc --noEmit"];
8 | }
9 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/core/src/config/stage-name.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Stage (environment) identifier. Local is for developer to deploy locally where all other stages are pipeline stages.
3 | */
4 | export enum StageName {
5 | Local = "local",
6 | Dev = "dev",
7 | Test = "test",
8 | Prod = "prod",
9 | }
10 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/config/stage-name.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Stage (environment) identifier. Local is for developer to deploy locally where all other stages are pipeline stages.
3 | */
4 | export enum StageName {
5 | Local = "local",
6 | Dev = "dev",
7 | Test = "test",
8 | Prod = "prod",
9 | }
10 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/pages/Root.tsx:
--------------------------------------------------------------------------------
1 | import { ReactElement } from "react";
2 | import { Navigate, ScrollRestoration } from "react-router-dom";
3 |
4 | export function Root(): ReactElement {
5 | return (
6 | <>
7 |
8 |
9 | >
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/config/server-config.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { ServerConfig as BaseServerConfig } from "@/core-server";
3 |
4 | export class ServerConfig extends BaseServerConfig {}
5 |
6 | export const serverConfig = new ServerConfig(
7 | process.env[ServerConfig.envVarNames.STAGE_NAME],
8 | );
9 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/create-item.use-case.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { itemRepo } from "./item.repo";
3 | import type { ItemInputSchema } from "./item.schema";
4 |
5 | export async function createItemUseCase(props: ItemInputSchema): Promise {
6 | await itemRepo.create(props);
7 | }
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/config/server-config.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { ServerConfig as BaseServerConfig } from "@/core-server";
3 |
4 | export class ServerConfig extends BaseServerConfig {}
5 |
6 | export const serverConfig = new ServerConfig(
7 | process.env[ServerConfig.envVarNames.STAGE_NAME],
8 | );
9 |
--------------------------------------------------------------------------------
/packages/gboost/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist",
5 | "noEmit": false
6 | },
7 | "exclude": [
8 | "templates/**/*",
9 | "examples/**/*",
10 | "src/**/*.test.ts",
11 | "tests/**/*",
12 | "scripts/**/*"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/docs/src/components/Link.tsx:
--------------------------------------------------------------------------------
1 | import NextLink from "next/link";
2 |
3 | export function Link(props: Parameters[0]) {
4 | return (
5 |
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/tsconfig/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@myapp/tsconfig",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": {
6 | "./*": "./*"
7 | },
8 | "devDependencies": {
9 | "@tsconfig/node18-strictest-esm": "^1.0.1",
10 | "@tsconfig/vite-react": "^1.0.1"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/public/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #da532c
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/config.ts:
--------------------------------------------------------------------------------
1 | import { StageName } from "@myapp/core";
2 |
3 | export const config = {
4 | apiUrl: String(import.meta.env.VITE_API_URL),
5 | mode: import.meta.env.MODE,
6 | stage: import.meta.env.VITE_STAGE,
7 | get isLocal() {
8 | return this.stage === StageName.Local;
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost Template: Minimal
2 |
3 | ## Deploy Infrastructure Locally
4 |
5 | 1. From the root of your monorepo, `cd infra`
6 | 2. `pnpm deploy:local`
7 |
8 | ## Clean Up Infrastructure Locally
9 |
10 | 1. From the root of your monorepo, `cd infra`
11 | 2. `pnpm destroy:local`
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/get-item.use-case.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import type { ItemEntity } from "./item.entity";
3 | import { itemRepo } from "./item.repo";
4 |
5 | export async function getItemUseCase(
6 | id: string,
7 | ): Promise {
8 | return itemRepo.get(id);
9 | }
10 |
--------------------------------------------------------------------------------
/packages/gboost/src/utils/handle-aborted.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/terkelg/prompts/issues/252#issuecomment-778683666
2 | export function handleAborted({ aborted }: { aborted: boolean }) {
3 | if (aborted) {
4 | process.nextTick(() => {
5 | console.log("\nStopping. Goodbye 👋");
6 | process.exit(0);
7 | });
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config@1.6.4/schema.json",
3 | "changelog": ["@changesets/changelog-github", { "repo": "awslabs/green-boost" }],
4 | "commit": false,
5 | "linked": [],
6 | "access": "public",
7 | "baseBranch": "main",
8 | "updateInternalDependencies": "patch",
9 | "ignore": []
10 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.codeActionsOnSave": {
3 | "source.fixAll.eslint": true
4 | },
5 | "typescript.preferences.importModuleSpecifierEnding": "js",
6 | "typescript.tsdk": "node_modules/typescript/lib",
7 | "search.exclude": {
8 | "**/node_modules": true,
9 | "**/cdk.out": true,
10 | }
11 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/src/pipeline/pipeline-app.ts:
--------------------------------------------------------------------------------
1 | import { App } from "aws-cdk-lib";
2 | import { configs } from "../config/configs.js";
3 | import { StageName } from "@myapp/core";
4 | import { PipelineStack } from "./pipeline-stack.js";
5 |
6 | const app = new App();
7 | new PipelineStack(app, "myapp-pipeline", { env: configs[StageName.Dev] });
8 |
--------------------------------------------------------------------------------
/packages/gboost-common/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/node18"],
3 | "compilerOptions": {
4 | "declaration": true,
5 | "declarationMap": true,
6 | "exactOptionalPropertyTypes": false,
7 | "incremental": true,
8 | "noEmit": true
9 | },
10 | "include": ["src/**/*", "scripts/**/*"]
11 | }
12 |
--------------------------------------------------------------------------------
/packages/gboost-infra/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/node18"],
3 | "compilerOptions": {
4 | "declaration": true,
5 | "declarationMap": true,
6 | "exactOptionalPropertyTypes": false,
7 | "incremental": true,
8 | "noEmit": true
9 | },
10 | "include": ["src/**/*", "scripts/**/*"]
11 | }
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/config/client-config.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { SharedConfig } from "@{{GB_APP_ID}}/core/shared";
3 |
4 | class ClientConfig extends SharedConfig {
5 | appTitle = "{{GB_APP_TITLE}}";
6 | }
7 |
8 | export const clientConfig = new ClientConfig(
9 | process.env["NEXT_PUBLIC_STAGE_NAME"],
10 | );
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/index.server.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | export { ServerConfig } from "./config/server-config";
3 | export {
4 | createItemUseCase,
5 | deleteItemUseCase,
6 | getItemUseCase,
7 | listItemsUseCase,
8 | updateItemUseCase,
9 | } from "./modules/item";
10 | export { logger } from "./adapters/secondary";
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/config/client-config.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { SharedConfig } from "@{{GB_APP_ID}}/core/shared";
3 |
4 | class ClientConfig extends SharedConfig {
5 | appTitle = "{{GB_APP_TITLE}}";
6 | }
7 |
8 | export const clientConfig = new ClientConfig(
9 | process.env["NEXT_PUBLIC_STAGE_NAME"],
10 | );
11 |
--------------------------------------------------------------------------------
/docs/.lintstagedrc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "*.ts?(x)": (files) => {
3 | const joinedFiles = files.join(" ");
4 | return [
5 | `eslint --max-warnings=0 --no-warn-ignored ${joinedFiles}`,
6 | `prettier --write ${joinedFiles}`,
7 | `vitest related --run ${joinedFiles}`,
8 | "tsc --noEmit",
9 | ];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/src/local-app.ts:
--------------------------------------------------------------------------------
1 | import { App } from "aws-cdk-lib";
2 | import { AppStage } from "./app-stage.js";
3 | import { configs } from "./config/configs.js";
4 | import { StageName } from "@myapp/core";
5 |
6 | const app = new App();
7 | const localConfig = configs[StageName.Local];
8 | new AppStage(app, localConfig.stageId, localConfig);
9 |
--------------------------------------------------------------------------------
/packages/gboost/.lintstagedrc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "*.ts": (files) => {
3 | const joinedFiles = files.join(" ");
4 | return [
5 | `eslint --max-warnings=0 --no-warn-ignored ${joinedFiles}`,
6 | `prettier --write ${joinedFiles}`,
7 | `vitest related --run ${joinedFiles}`,
8 | "tsc --noEmit",
9 | ];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/goodbye/[name]/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { Goodbye } from "./Goodbye";
3 |
4 | interface PageProps {
5 | params: { name: string };
6 | }
7 |
8 | export default function Page(props: PageProps) {
9 | const {
10 | params: { name },
11 | } = props;
12 | return ;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/update-item.use-case.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { itemRepo } from "./item.repo";
3 | import type { UpdateItemInputSchema } from "./item.schema";
4 |
5 | export async function updateItemUseCase(
6 | props: UpdateItemInputSchema,
7 | ): Promise {
8 | await itemRepo.update(props);
9 | }
10 |
--------------------------------------------------------------------------------
/docs/src/pages/overview/common-error-resolutions.mdx:
--------------------------------------------------------------------------------
1 | # Common Error Resolutions
2 |
3 | ## CDK
4 | - Error: `ChangeSet [PipelineChange] does not exist (Service: AmazonCloudFormation; Status Code: 404; Error Code: ChangeSetNotFound; Request ID: ...)`
5 | - Resolution: Start the pipeline execution again by selecting "Release change" button at top of AWS Console CodePipeline UI.
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/.lintstagedrc.js.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { removeIgnoredFiles } from "@myapp/utils";
3 |
4 | export default {
5 | "*.ts": async (files) => {
6 | const filesToLint = await removeIgnoredFiles(files);
7 | return [`eslint --fix --max-warnings=0 ${filesToLint}`, `vitest --passWithNoTests related ${files}`, "tsc --noEmit"];
8 | }
9 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/entrypoints/api/router.ts:
--------------------------------------------------------------------------------
1 | import { widgetRouter } from "./routers/widget.js";
2 | import { t } from "./trpc.js";
3 | import { componentRouter } from "./routers/components.js";
4 |
5 | export const router = t.router({
6 | widget: widgetRouter,
7 | component: componentRouter,
8 | });
9 | export type AppRouter = typeof router;
10 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/.lintstagedrc.js.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { removeIgnoredFiles } from "@myapp/utils";
3 |
4 | export default {
5 | "*.ts": async (files) => {
6 | const filesToLint = await removeIgnoredFiles(files);
7 | return [`eslint --fix --max-warnings=0 ${filesToLint}`, `vitest --passWithNoTests related ${files}`, "tsc --noEmit"];
8 | }
9 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/.lintstagedrc.js.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { removeIgnoredFiles } from "@myapp/utils";
3 |
4 | export default {
5 | "*.ts?(x)": async (files) => {
6 | const filesToLint = await removeIgnoredFiles(files);
7 | return [`eslint --fix --max-warnings=0 ${filesToLint}`, `vitest --passWithNoTests related ${files}`, "tsc --noEmit"];
8 | }
9 | }
--------------------------------------------------------------------------------
/packages/gboost-common/.lintstagedrc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "*.ts": (files) => {
3 | const joinedFiles = files.join(" ");
4 | return [
5 | `eslint --max-warnings=0 --no-warn-ignored ${joinedFiles}`,
6 | `prettier --write ${joinedFiles}`,
7 | `vitest related --run ${joinedFiles}`,
8 | "tsc --noEmit",
9 | ];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/packages/gboost-infra/.lintstagedrc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "*.ts": (files) => {
3 | const joinedFiles = files.join(" ");
4 | return [
5 | `eslint --max-warnings=0 --no-warn-ignored ${joinedFiles}`,
6 | `prettier --write ${joinedFiles}`,
7 | `vitest related --run ${joinedFiles}`,
8 | "tsc --noEmit",
9 | ];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/packages/gboost-node/.lintstagedrc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "*.ts": (files) => {
3 | const joinedFiles = files.join(" ");
4 | return [
5 | `eslint --max-warnings=0 --no-warn-ignored ${joinedFiles}`,
6 | `prettier --write ${joinedFiles}`,
7 | `vitest related --run ${joinedFiles}`,
8 | "tsc --noEmit",
9 | ];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/packages/gboost-ui/.lintstagedrc.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "*.ts?(x)": (files) => {
3 | const joinedFiles = files.join(" ");
4 | return [
5 | `eslint --max-warnings=0 --no-warn-ignored ${joinedFiles}`,
6 | `prettier --write ${joinedFiles}`,
7 | `vitest related --run ${joinedFiles}`,
8 | "tsc --noEmit",
9 | ];
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/components/LoadingH2.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use client";
3 |
4 | import Skeleton from "@mui/material/Skeleton";
5 | import Typography from "@mui/material/Typography";
6 |
7 | export function LoadingH2() {
8 | return (
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/packages/tsconfig/package.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@{{GB_APP_ID}}/tsconfig",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": {
6 | "./*": "./*"
7 | },
8 | "devDependencies": {
9 | "@tsconfig/next": "^2.0.1",
10 | "@tsconfig/node18": "^18.2.2",
11 | "@tsconfig/strictest": "^2.0.2"
12 | }
13 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/hello/[name]/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { Hello } from "@/app/hello/[name]/Hello";
3 |
4 | interface PageProps {
5 | params: { name: string };
6 | }
7 |
8 | export default function Page(props: PageProps) {
9 | const {
10 | params: { name },
11 | } = props;
12 | return ;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/base/base.entity.ts:
--------------------------------------------------------------------------------
1 | import {
2 | baseSchema,
3 | type BaseSchema,
4 | type BaseInputSchema,
5 | } from "./base.schema";
6 |
7 | export abstract class BaseEntity {
8 | readonly props: BaseSchema;
9 |
10 | constructor(props: BaseInputSchema) {
11 | this.props = baseSchema.parse(props);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/drizzle/0001_loud_serpent_society.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS "{{GB_SQL_APP_ID}}"."item" (
2 | "created_at" timestamp with time zone DEFAULT now() NOT NULL,
3 | "description" text NOT NULL,
4 | "id" uuid PRIMARY KEY NOT NULL,
5 | "name" text NOT NULL,
6 | "updated_at" timestamp with time zone DEFAULT now() NOT NULL
7 | );
8 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/domain/models/widget-component.ts:
--------------------------------------------------------------------------------
1 | import { Base } from "./base.js";
2 |
3 | export class WidgetComponent extends Base {
4 | widgetId: string;
5 | componentId: string;
6 | constructor(params: WidgetComponent) {
7 | super(params);
8 | this.widgetId = params.widgetId;
9 | this.componentId = params.componentId;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/types/page-props.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import type { SearchParams } from "@{{GB_APP_ID}}/core/shared";
3 |
4 | /**
5 | * Generic Next.js props for page.tsx function.
6 | */
7 | export type PageProps<
8 | T extends Record = Record,
9 | > = {
10 | params: T;
11 | searchParams?: SearchParams;
12 | };
13 |
--------------------------------------------------------------------------------
/packages/gboost-infra/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "dist",
5 | "noEmit": false
6 | },
7 | "exclude": [
8 | "src/**/*.test.ts",
9 | // custom resource functions are bundled by esbuild. see scripts/build.ts
10 | "./src/web-deployment/web-deploy-cr-handler/**",
11 | "scripts/**/*"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/docs/src/pages/learn/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "intro": "Introduction",
3 | "m1-deploy-gb-app": "M1: Deploy Green Boost Template App",
4 | "m2-js-ts": "M2: JavaScript/TypeScript",
5 | "m3-infra": "M3: Infrastructure",
6 | "m4-backend": "M4: Backend",
7 | "m5-frontend": "M5: Frontend",
8 | "m6-tooling": "M6: Tooling",
9 | "m7-clean-code": "M7: Clean Code",
10 | "resources": "Resources"
11 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/index.shared.ts:
--------------------------------------------------------------------------------
1 | export { SharedConfig } from "./config/shared-config";
2 | export { StageName } from "./config/stage-name";
3 | export { type SearchParams } from "./types";
4 | export {
5 | type ItemSchema,
6 | type ItemInputSchema,
7 | itemSchema,
8 | updateItemSchema,
9 | type UpdateItemInputSchema,
10 | } from "./modules/item/index.shared";
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/drizzle/meta/0000_snapshot.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "92d1c54f-e2c6-44d5-afdc-e5ae23453215",
3 | "prevId": "00000000-0000-0000-0000-000000000000",
4 | "version": "5",
5 | "dialect": "pg",
6 | "tables": {},
7 | "enums": {},
8 | "schemas": {},
9 | "_meta": {
10 | "columns": {},
11 | "schemas": {},
12 | "tables": {}
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/next"],
3 | "compilerOptions": {
4 | "exactOptionalPropertyTypes": false,
5 | "paths": {
6 | "@/*": ["./src/*"],
7 | },
8 | },
9 | "include": [
10 | "next-env.d.ts",
11 | "**/*.ts",
12 | "**/*.tsx",
13 | ".next/types/**/*.ts"
14 | ],
15 | "exclude": [
16 | "node_modules",
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@myapp/eslint-config-node"],
7 | rules: {
8 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/db/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@myapp/eslint-config-node"],
7 | rules: {
8 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@myapp/eslint-config-node"],
7 | rules: {
8 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/app/items/[id]/update-item.action.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use server";
3 |
4 | import { updateItemUseCase } from "@/core-server";
5 | import { revalidatePath } from "next/cache";
6 |
7 | export async function updateItemAction(
8 | props: Parameters[0],
9 | ) {
10 | await updateItemUseCase(props);
11 | revalidatePath("/items");
12 | }
13 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/app/items/new/create-item.action.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use server";
3 |
4 | import { createItemUseCase } from "@/core-server";
5 | import { revalidatePath } from "next/cache";
6 |
7 | export async function createItemAction(
8 | props: Parameters[0],
9 | ) {
10 | await createItemUseCase(props);
11 | revalidatePath("/items");
12 | }
13 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/pages/widgets/WidgetsAdditionalActions.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@aws-amplify/ui-react";
2 | import { ReactElement } from "react";
3 | import { Link } from "react-router-dom";
4 |
5 | export function WidgetsAdditionalActions(): ReactElement {
6 | return (
7 |
8 |
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/packages/gboost-common/src/convert-case.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, test, expect } from "vitest";
2 | import { camelToKebab } from "./convert-case.js";
3 |
4 | describe("convertCase.ts", () => {
5 | const camelCase = "longVariableName";
6 | const kebabCase = "long-variable-name";
7 | test(`${camelCase} to kebabCase ${kebabCase}`, () => {
8 | expect(camelToKebab(camelCase)).toBe(kebabCase);
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/core/.lintstagedrc.js.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { removeIgnoredFiles } from "@GB_APP_ID/utils";
3 |
4 | export default {
5 | "*.ts": async (files) => {
6 | const filesToLint = await removeIgnoredFiles(files);
7 | return [
8 | `eslint --fix --max-warnings=0 ${filesToLint}`,
9 | `vitest related --run ${files}`,
10 | "tsc --noEmit",
11 | ];
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/packages/gboost/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/node18"],
3 | "compilerOptions": {
4 | // don't need declaration map b/c end user is only running as cli
5 | "exactOptionalPropertyTypes": false,
6 | "incremental": true,
7 | "noEmit": true
8 | },
9 | "include": ["src/**/*", "tests/**/*", "scripts/**/*"],
10 | "exclude": ["templates/**/*", "examples/**/*"]
11 | }
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost
2 | 
3 |
4 | Build Full Stack Serverless Web Apps on AWS Fast
5 |
6 | Docs: https://awslabs.github.io/green-boost/
7 |
8 | ## Security
9 |
10 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
11 |
12 | ## License
13 |
14 | This project is licensed under the Apache-2.0 License.
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/utils/index.js:
--------------------------------------------------------------------------------
1 | import { ESLint } from "eslint";
2 |
3 | export async function removeIgnoredFiles(files) {
4 | const eslint = new ESLint();
5 | const isIgnored = await Promise.all(
6 | files.map((file) => {
7 | return eslint.isPathIgnored(file);
8 | })
9 | );
10 | const filteredFiles = files.filter((_, i) => !isIgnored[i]);
11 | return filteredFiles.join(" ");
12 | }
13 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/components/layout/Footer.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { clientConfig } from "@/config/client-config";
3 | import { Typography } from "@mui/material";
4 | import { type ReactElement } from "react";
5 |
6 | export function Footer(): ReactElement {
7 | return (
8 |
9 | {clientConfig.appTitle}
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/infra/.lintstagedrc.js.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { removeIgnoredFiles } from "@GB_APP_ID/utils";
3 |
4 | export default {
5 | "*.ts": async (files) => {
6 | const filesToLint = await removeIgnoredFiles(files);
7 | return [
8 | `eslint --fix --max-warnings=0 ${filesToLint}`,
9 | `vitest related --run ${files}`,
10 | "tsc --noEmit",
11 | ];
12 | },
13 | };
14 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/infra/src/local-app.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { App } from "aws-cdk-lib";
3 | import { AppStage } from "./app-stage";
4 | import { Config } from "./config/config";
5 | import { userInfo } from "node:os";
6 |
7 | const app = new App();
8 | const localConfig = new Config(
9 | process.env["STAGE_NAME"] || userInfo().username,
10 | );
11 | new AppStage(app, localConfig.stageId, localConfig);
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/infra/src/local-app.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { App } from "aws-cdk-lib";
3 | import { AppStage } from "./app-stage";
4 | import { Config } from "./config/config";
5 | import { userInfo } from "node:os";
6 |
7 | const app = new App();
8 | const localConfig = new Config(
9 | process.env["STAGE_NAME"] || userInfo().username,
10 | );
11 | new AppStage(app, localConfig.stageId, localConfig);
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/schema.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { pgSchema } from "drizzle-orm/pg-core";
3 |
4 | // schema is created in custom migration file with {{GB_SQL_APP_ID}}_iam_user so that DB IAM
5 | // user has access to all tables within this schema
6 | // want to use config.appId but https://github.com/drizzle-team/drizzle-kit-mirror/issues/55
7 | export const schema = pgSchema("{{GB_SQL_APP_ID}}");
8 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/core/.eslintrc.cjs.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@{{GB_APP_ID}}/eslint-config-node"],
7 | rules: {
8 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/infra/.eslintrc.cjs.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@{{GB_APP_ID}}/eslint-config-node"],
7 | rules: {
8 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/components/layout/Footer.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { clientConfig } from "@/config/client-config";
3 | import Typography from "@mui/material/Typography";
4 | import { type ReactElement } from "react";
5 |
6 | export function Footer(): ReactElement {
7 | return (
8 |
9 | {clientConfig.appTitle}
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/utils/kebab-to-title.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, test } from "vitest";
2 | import { kebabToTitle } from "./kebab-to-title";
3 |
4 | describe("kebab-to-title", () => {
5 | test("one word case", () => {
6 | expect(kebabToTitle("world")).toBe("World");
7 | });
8 | test("two words case", () => {
9 | expect(kebabToTitle("john-smith")).toBe("John Smith");
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/packages/utils/index.js:
--------------------------------------------------------------------------------
1 | import { ESLint } from "eslint";
2 |
3 | export async function removeIgnoredFiles(files) {
4 | const eslint = new ESLint();
5 | const isIgnored = await Promise.all(
6 | files.map((file) => {
7 | return eslint.isPathIgnored(file);
8 | }),
9 | );
10 | const filteredFiles = files.filter((_, i) => !isIgnored[i]);
11 | return filteredFiles.join(" ");
12 | }
13 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/infra/src/pipeline/pipeline-app.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { App } from "aws-cdk-lib";
3 | import { StageName } from "@{{GB_APP_ID}}/core/shared";
4 | import { PipelineStack } from "./pipeline-stack";
5 | import { Config } from "../config/config";
6 |
7 | const app = new App();
8 | const devConfig = new Config(StageName.Dev);
9 | new PipelineStack(app, "{{GB_APP_ID}}-pipeline", { env: devConfig.env });
10 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/infra/src/pipeline/pipeline-app.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { App } from "aws-cdk-lib";
3 | import { StageName } from "@{{GB_APP_ID}}/core/shared";
4 | import { PipelineStack } from "./pipeline-stack";
5 | import { Config } from "../config/config";
6 |
7 | const app = new App();
8 | const devConfig = new Config(StageName.Dev);
9 | new PipelineStack(app, "{{GB_APP_ID}}-pipeline", { env: devConfig.env });
10 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/tsconfig.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@{{GB_APP_ID}}/tsconfig/tsconfig.next.json"],
3 | "compilerOptions": {
4 | "exactOptionalPropertyTypes": false,
5 | "paths": {
6 | "@/*": ["./src/*"],
7 | }
8 | },
9 | "include": [
10 | "next-env.d.ts",
11 | "**/*.ts",
12 | "**/*.tsx",
13 | ".next/types/**/*.ts"
14 | ],
15 | "exclude": [
16 | "node_modules",
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/web-deployment/common.ts:
--------------------------------------------------------------------------------
1 | export interface InputResourceProperties {
2 | sourceBucketName: string;
3 | sourceObjectKey: string;
4 | destinationBucketName: string;
5 | destinationObjectKeyPrefix: string;
6 | environment: Record;
7 | distributionId?: string;
8 | prune: boolean;
9 | }
10 |
11 | export interface ResourceProperties extends InputResourceProperties {
12 | ServiceToken: string;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/gboost/scripts/build.ts:
--------------------------------------------------------------------------------
1 | import { execSync } from "node:child_process";
2 | import { rmSync } from "node:fs";
3 | import { resolve } from "node:path";
4 | import { fileURLToPath } from "node:url";
5 |
6 | const thisFilePath = fileURLToPath(import.meta.url);
7 | const outDir = resolve(thisFilePath, `../dist`);
8 | rmSync(outDir, { recursive: true, force: true });
9 | execSync("pnpm tsc --project tsconfig.build.json", { stdio: "inherit" });
10 |
--------------------------------------------------------------------------------
/packages/gboost-common/scripts/build.ts:
--------------------------------------------------------------------------------
1 | import { execSync } from "node:child_process";
2 | import { rmSync } from "node:fs";
3 | import { resolve } from "node:path";
4 | import { fileURLToPath } from "node:url";
5 |
6 | const thisFilePath = fileURLToPath(import.meta.url);
7 | const outDir = resolve(thisFilePath, `../dist`);
8 | rmSync(outDir, { recursive: true, force: true });
9 | execSync("pnpm tsc --project tsconfig.build.json", { stdio: "inherit" });
10 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/user-management/function/validateUsernames.ts:
--------------------------------------------------------------------------------
1 | import Joi from "joi";
2 |
3 | export interface UsernameArgs {
4 | usernames: string[];
5 | }
6 |
7 | let schema: undefined | Joi.ObjectSchema;
8 | export function validate(args: UsernameArgs) {
9 | if (!schema) {
10 | schema = Joi.object({
11 | usernames: Joi.array().items(Joi.string().max(128)).required(),
12 | });
13 | }
14 | Joi.assert(args, schema);
15 | }
16 |
--------------------------------------------------------------------------------
/packages/gboost-node/scripts/build.ts:
--------------------------------------------------------------------------------
1 | import { execSync } from "node:child_process";
2 | import { rmSync } from "node:fs";
3 | import { resolve } from "node:path";
4 | import { fileURLToPath } from "node:url";
5 |
6 | const thisFilePath = fileURLToPath(import.meta.url);
7 | const outDir = resolve(thisFilePath, `../dist`);
8 | rmSync(outDir, { recursive: true, force: true });
9 | execSync("pnpm tsc --project tsconfig.build.json", { stdio: "inherit" });
10 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/base/base.schema.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { z } from "zod";
3 |
4 | const datetime = z
5 | .string()
6 | .datetime()
7 | .default(() => new Date().toISOString());
8 |
9 | export const baseSchema = z.object({
10 | createdAt: datetime,
11 | updatedAt: datetime,
12 | });
13 | export type BaseSchema = z.infer;
14 | export type BaseInputSchema = z.input;
15 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/file-upload/function/findIndex.ts:
--------------------------------------------------------------------------------
1 | export function findIndex(
2 | bucketMap: { bucket: string; baseKey: string }[],
3 | bucket: string,
4 | ) {
5 | let i = 0;
6 | let notFound = true;
7 | while (notFound && i < bucketMap.length) {
8 | if (bucketMap[i]?.bucket === bucket) {
9 | notFound = false;
10 | } else {
11 | i++;
12 | }
13 | }
14 | if (notFound) {
15 | i = -1;
16 | }
17 | return i;
18 | }
19 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/.lintstagedrc.js.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import { removeIgnoredFiles } from "@GB_APP_ID/utils";
3 |
4 | export default {
5 | "*.ts?(x)": async (files) => {
6 | const filesToLint = await removeIgnoredFiles(files);
7 | // TODO: use setup here: https://nextjs.org/docs/pages/building-your-application/configuring/eslint#lint-staged
8 | return [`next lint`, `vitest related --run ${files}`, "tsc --noEmit"];
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/.eslintrc.cjs.t:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@{{GB_APP_ID}}/eslint-config-next"],
7 | ignorePatterns: [".next/**"],
8 | rules: {
9 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/packages/gboost-common/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost Common Library
2 |
3 | 
4 |
5 | Build Full Stack Serverless Web Apps on AWS Fast
6 |
7 | Documentation: https://awslabs.github.io/green-boost/
8 |
9 | ## Security
10 |
11 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
12 |
13 | ## License
14 |
15 | This project is licensed under the Apache-2.0 License.
16 |
--------------------------------------------------------------------------------
/docs/src/pages/overview/contributors/resources.mdx:
--------------------------------------------------------------------------------
1 | # Resources
2 |
3 | Building a library whether for React components, CDK Constructs, or Node.js takes skill.
4 |
5 | # React
6 | - [Advanced React Component Composition Guide](https://frontendmastery.com/posts/advanced-react-component-composition-guide/)
7 | - [Building Future Facing Frontend Architectures](https://frontendmastery.com/posts/building-future-facing-frontend-architectures/)
8 | # AWS CDK
9 | - TODO
10 | # Node.js
11 | - TODO
--------------------------------------------------------------------------------
/packages/gboost-node/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost Node.js Library
2 |
3 | 
4 |
5 | Build Full Stack Serverless Web Apps on AWS Fast
6 |
7 | Documentation: https://awslabs.github.io/green-boost/
8 |
9 | ## Security
10 |
11 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
12 |
13 | ## License
14 |
15 | This project is licensed under the Apache-2.0 License.
16 |
--------------------------------------------------------------------------------
/packages/gboost/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost Command Line Interface
2 |
3 | 
4 |
5 | Build Full Stack Serverless Web Apps on AWS Fast
6 |
7 | Documentation: https://awslabs.github.io/green-boost/
8 |
9 | ## Security
10 |
11 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
12 |
13 | ## License
14 |
15 | This project is licensed under the Apache-2.0 License.
16 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/index.ts:
--------------------------------------------------------------------------------
1 | export { createItemUseCase } from "./create-item.use-case";
2 | export { deleteItemUseCase } from "./delete-item.use-case";
3 | export { getItemUseCase } from "./get-item.use-case";
4 | export { listItemsUseCase } from "./list-items.use-case";
5 | export { updateItemUseCase } from "./update-item.use-case";
6 | export {
7 | type ItemSchema,
8 | itemSchema,
9 | type ItemInputSchema,
10 | } from "./item.schema";
11 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/item.entity.ts:
--------------------------------------------------------------------------------
1 | import { BaseEntity } from "../base";
2 | import {
3 | itemSchema,
4 | type ItemSchema,
5 | type ItemInputSchema,
6 | } from "./item.schema";
7 |
8 | /**
9 | * Items
10 | */
11 | export class ItemEntity extends BaseEntity {
12 | override readonly props: ItemSchema;
13 |
14 | constructor(props: ItemInputSchema) {
15 | super(props);
16 | this.props = itemSchema.parse(props);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/gboost-ui/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost UI Component Library
2 |
3 | 
4 |
5 | Build Full Stack Serverless Web Apps on AWS Fast
6 |
7 | Documentation: https://awslabs.github.io/green-boost/
8 |
9 | ## Security
10 |
11 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
12 |
13 | ## License
14 |
15 | This project is licensed under the Apache-2.0 License.
16 |
--------------------------------------------------------------------------------
/.github/actions/install/action.yml:
--------------------------------------------------------------------------------
1 | name: Install
2 | description: Install PNPM, Node.js, and dependencies
3 | runs:
4 | using: composite
5 | steps:
6 | - name: Install PNPM
7 | uses: pnpm/action-setup@v2
8 | with:
9 | version: 8
10 |
11 | - name: Install Node.js
12 | uses: actions/setup-node@v3
13 | with:
14 | node-version: 18.x
15 | cache: pnpm
16 |
17 | - name: Install dependencies
18 | run: pnpm install
19 | shell: bash
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.codeActionsOnSave": {
3 | "source.fixAll.eslint": "explicit"
4 | },
5 | "editor.defaultFormatter": "esbenp.prettier-vscode",
6 | "editor.formatOnSave": true,
7 | "eslint.useFlatConfig": true,
8 | "files.associations": {
9 | "*.css": "tailwindcss"
10 | },
11 | "typescript.tsdk": "node_modules/typescript/lib",
12 | "search.exclude": {
13 | "**/node_modules": true,
14 | "**/cdk.out": true,
15 | "packages/*/dist": true,
16 | }
17 | }
--------------------------------------------------------------------------------
/packages/gboost-infra/src/static-site/rewrite-url.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2 | // @ts-ignore handler is called by CloudFront function runtime
3 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
4 | function handler(event) {
5 | var request = event.request;
6 | var uri = request.uri;
7 | // check whether URI is missing file extension
8 | if (!uri.includes(".")) {
9 | request.uri = "/index.html";
10 | }
11 | return request;
12 | }
13 |
--------------------------------------------------------------------------------
/packages/gboost-common/src/index.ts:
--------------------------------------------------------------------------------
1 | export {
2 | camelToKebab,
3 | camelToSnake,
4 | lowerToPascal,
5 | pascalToKebabCase,
6 | } from "./convert-case.js";
7 | export {
8 | type CognitoGroup,
9 | type CognitoUser,
10 | CognitoUserStatus,
11 | CreateCognitoUser,
12 | type Filter,
13 | type ListUsersArgs,
14 | type ListUsersInGroupArgs,
15 | } from "./user-management.js";
16 | export { mergeDeep } from "./merge-deep.js";
17 | export { getErrorMessage } from "./get-error-message.js";
18 |
--------------------------------------------------------------------------------
/packages/gboost-infra/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost Infrastructure Construct Library
2 |
3 | 
4 |
5 | Build Full Stack Serverless Web Apps on AWS Fast
6 |
7 | Documentation: https://awslabs.github.io/green-boost/
8 |
9 | ## Security
10 |
11 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
12 |
13 | ## License
14 |
15 | This project is licensed under the Apache-2.0 License.
16 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/eslint-config-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@myapp/eslint-config-react",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": "./.eslintrc.cjs",
6 | "devDependencies": {
7 | "eslint": "^8.36.0",
8 | "eslint-config-prettier": "^8.7.0",
9 | "eslint-config-react-app": "^7.0.1",
10 | "eslint-define-config": "^1.16.0",
11 | "eslint-plugin-prettier": "^4.0.0",
12 | "prettier": "^2.8.0",
13 | "typescript": "^4.9.3"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/user-base/pre-token-generation.ts:
--------------------------------------------------------------------------------
1 | import type { PreTokenGenerationTriggerHandler } from "aws-lambda";
2 |
3 | export const handler: PreTokenGenerationTriggerHandler = async (event) => {
4 | const groups = event.request.userAttributes["custom:groups"];
5 | if (groups) {
6 | event.response = {
7 | claimsOverrideDetails: {
8 | groupOverrideDetails: {
9 | groupsToOverride: [groups],
10 | },
11 | },
12 | };
13 | }
14 | return event;
15 | };
16 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Green Boost Examples
2 |
3 | Examples are production-grade web apps built with Green Boost that solve a business problem. They have specific requirements and may take many manual steps to deploy. They're not meant for use as a "quick start". Templates created from `gboost create` on the other hand are simple web apps meeting more generic use cases meant for developers to build on top off. Templates are easy to get started with. You're welcome to deploy these example apps and utilize patterns and code found within them.
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/scripts/seed-items.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { dbWrite } from "../../adapters/secondary";
3 | import type { ItemInputSchema } from "../../index.shared";
4 | import { item } from "../../modules/item/item.db";
5 |
6 | const items: ItemInputSchema[] = [];
7 |
8 | for (const _i of Array(50).keys()) {
9 | items.push({
10 | name: `Item ${_i}`,
11 | description: `Item ${_i}'s Description`,
12 | });
13 | }
14 |
15 | await dbWrite.insert(item).values(items).execute();
16 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/drizzle/0000_boring_maginty.sql:
--------------------------------------------------------------------------------
1 | -- Custom SQL migration file, put you code below! --
2 | create schema {{GB_SQL_APP_ID}};
3 | create role {{GB_SQL_APP_ID}}_iam_user with login;
4 | grant rds_iam to {{GB_SQL_APP_ID}}_iam_user;
5 | grant usage on schema {{GB_SQL_APP_ID}} to {{GB_SQL_APP_ID}}_iam_user;
6 | -- https://gist.github.com/zaenk/2e9c1936663caae71b212f056b5dfb5f
7 | alter default privileges in schema {{GB_SQL_APP_ID}} grant insert, update, delete, select on tables to {{GB_SQL_APP_ID}}_iam_user;
--------------------------------------------------------------------------------
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/aspects/suppress-nags/suppress-cdk-custom-resource.ts:
--------------------------------------------------------------------------------
1 | import { NagSuppressions } from "cdk-nag";
2 | import type { IConstruct } from "constructs";
3 |
4 | export function suppressCdkCustomResource(construct: IConstruct) {
5 | if (construct.node.path.match(/^.+\/AWS[a-z0-9]{32}\/Resource$/)) {
6 | NagSuppressions.addResourceSuppressions(construct, [
7 | {
8 | id: "AwsSolutions-L1",
9 | reason: "AWS CDK team will update runtime if security issue arises",
10 | },
11 | ]);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/db/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@myapp/db",
3 | "version": "0.1.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "lint": "eslint \"src/**/*.ts\"",
8 | "watch": "tsc -w",
9 | "typecheck": "tsc --noEmit"
10 | },
11 | "devDependencies": {
12 | "@myapp/eslint-config-node": "workspace:^",
13 | "@myapp/tsconfig": "workspace:^",
14 | "@myapp/utils": "workspace:^",
15 | "eslint": "^8.36.0",
16 | "eslint-define-config": "^1.16.0",
17 | "typescript": "^4.9.4"
18 | }
19 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/infra/src/utils/get-db-fn-props.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { SubnetType } from "aws-cdk-lib/aws-ec2";
3 | import type { DbIamCluster, FunctionProps } from "gboost-infra";
4 |
5 | /**
6 | * Get function props needed to connect Node.js Lambda Function to Aurora PostgreSQL DB
7 | */
8 | export function getDbFnProps(
9 | cluster: DbIamCluster,
10 | ): Omit {
11 | return {
12 | vpc: cluster.vpc,
13 | vpcSubnets: { subnetType: SubnetType.PRIVATE_WITH_EGRESS },
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /.open-next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/utils/date.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Given UTC ISO timestamp, return local-datetime input value
3 | */
4 | export function getLocalDateTimeInputValue(date: string) {
5 | const d = new Date(date);
6 | const year = d.getFullYear();
7 | const month = String(d.getMonth() + 1).padStart(2, "0");
8 | const day = String(d.getDate()).padStart(2, "0");
9 | const hours = String(d.getHours()).padStart(2, "0");
10 | const minutes = String(d.getMinutes()).padStart(2, "0");
11 | return `${year}-${month}-${day}T${hours}:${minutes}`;
12 | }
13 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/packages/eslint-config-next/package.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@{{GB_APP_ID}}/eslint-config-next",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": "./.eslintrc.cjs",
6 | "devDependencies": {
7 | "eslint": "^8.53.0",
8 | "eslint-config-next": "^14.0.3",
9 | "eslint-config-prettier": "^9.0.0",
10 | "eslint-define-config": "^2.0.0",
11 | "eslint-plugin-prettier": "^5.0.1",
12 | "eslint-plugin-security": "^1.7.1",
13 | "prettier": "^3.1.0",
14 | "typescript": "^5.2.2"
15 | }
16 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/eslint-config-node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@myapp/eslint-config-node",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": "./.eslintrc.cjs",
6 | "devDependencies": {
7 | "@typescript-eslint/eslint-plugin": "^5.55.0",
8 | "@typescript-eslint/parser": "^5.55.0",
9 | "eslint": "^8.36.0",
10 | "eslint-config-prettier": "^8.7.0",
11 | "eslint-define-config": "^1.16.0",
12 | "eslint-plugin-prettier": "^4.0.0",
13 | "prettier": "^2.8.0",
14 | "typescript": "^4.9.3"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/main.tsx:
--------------------------------------------------------------------------------
1 | import "@aws-amplify/ui-react/styles.css";
2 | import "@fontsource/inter/variable.css";
3 | import { createRoot } from "react-dom/client";
4 | import { StrictMode } from "react";
5 | import { RouterProvider } from "react-router-dom";
6 | import { router } from "./router.js";
7 |
8 | const container = document.getElementById("app");
9 | if (container) {
10 | const root = createRoot(container);
11 | root.render(
12 |
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/utils/format.ts:
--------------------------------------------------------------------------------
1 | const currencyFormatter = Intl.NumberFormat("default", {
2 | currency: "USD",
3 | style: "currency",
4 | });
5 |
6 | export function formatCurrency(n: number): string {
7 | return currencyFormatter.format(n);
8 | }
9 |
10 | const dateTimeFormatter = Intl.DateTimeFormat("default", {
11 | hour: "numeric",
12 | minute: "numeric",
13 | month: "numeric",
14 | year: "numeric",
15 | day: "numeric",
16 | });
17 | export function formatDateTime(date: string) {
18 | return dateTimeFormatter.format(new Date(date));
19 | }
20 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/app/items/[id]/page.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { getItemUseCase } from "@/core-server";
3 | import type { PageProps } from "@/types/page-props";
4 | import { UpdateItem } from "./UpdateItem";
5 | import { redirect } from "next/navigation";
6 |
7 | export default async function Page({ params }: PageProps<{ id: string }>) {
8 | const { id } = params;
9 | const item = await getItemUseCase(id);
10 | if (item) {
11 | return ;
12 | } else {
13 | return redirect("/item");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{GB_APP_NAME}}",
3 | "short_name": "{{GB_APP_NAME}}",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#18ab4b",
17 | "background_color": "#18ab4b",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/core-server.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | // Purpose of this file to safeguard agaginst importing server code/configuration
3 | // into client components. To do this, we restrict imports to @{{GB_APP_ID}}/core/server
4 | // via ESLint but temporarily disable the rule for this file. Then we use
5 | // "server-only" package which ensures this file is only imported in server components.
6 | import "server-only"; // prevents server code from being bundled into client code
7 | // eslint-disable-next-line no-restricted-imports
8 | export * from "@{{GB_APP_ID}}/core/server";
9 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/core-server.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | // Purpose of this file to safeguard agaginst importing server code/configuration
3 | // into client components. To do this, we restrict imports to @{{GB_APP_ID}}/core/server
4 | // via ESLint but temporarily disable the rule for this file. Then we use
5 | // "server-only" package which ensures this file is only imported in server components.
6 | import "server-only"; // prevents server code from being bundled into client code
7 | // eslint-disable-next-line no-restricted-imports
8 | export * from "@{{GB_APP_ID}}/core/server";
9 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/ui/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /.open-next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/aspects/gov-cloud-compat.ts:
--------------------------------------------------------------------------------
1 | import type { IAspect } from "aws-cdk-lib";
2 | import { CfnFunction } from "aws-cdk-lib/aws-lambda";
3 | import type { IConstruct } from "constructs";
4 |
5 | /**
6 | * Fix compatability issues with gboost-infra constructs and AWS GovCloud. For
7 | * example, change all arm64 Lambdas to x86_64
8 | */
9 | export class GovCloudCompat implements IAspect {
10 | visit(node: IConstruct) {
11 | if (node instanceof CfnFunction) {
12 | const fn = node as CfnFunction;
13 | fn.architectures = ["x86_64"];
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/packages/gboost-ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@tsconfig/strictest", "@tsconfig/next"],
3 | "compilerOptions": {
4 | "checkJs": false, // remove once fixAmplify.js is removed
5 | // uncomment below once stitches code is removed!
6 | // https://github.com/stitchesjs/stitches/issues/1055
7 | // "declaration": true,
8 | // "declarationMap": true,
9 | "exactOptionalPropertyTypes": false,
10 | "noEmit": true,
11 | "incremental": true,
12 | "target": "ES2015" // allows for of loop
13 | },
14 | "include": ["src/**/*.ts", "src/**/*.tsx", "scripts/**/*"]
15 | }
16 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/core/src/modules/item/list-items.use-case.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import type { ItemEntity } from "./item.entity";
3 | import type { SearchParams } from "../../types";
4 | import { itemRepo } from "./item.repo";
5 | import { listItemsSchema, type ListItemsInputSchema } from "./item.schema";
6 |
7 | type ListBatchesUseCaseProps = ListItemsInputSchema | SearchParams | undefined;
8 | export function listItemsUseCase(
9 | props: ListBatchesUseCaseProps,
10 | ): Promise {
11 | const result = listItemsSchema.parse(props);
12 | return itemRepo.list(result);
13 | }
14 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/core/package.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@{{GB_APP_ID}}/core",
3 | "version": "0.1.0",
4 | "private": true,
5 | "type": "module",
6 | "exports": {
7 | "./server": "./src/index.server.ts",
8 | "./shared": "./src/index.shared.ts"
9 | },
10 | "scripts": {
11 | "lint": "eslint \"src/**/*.ts\"",
12 | "test": "vitest run",
13 | "watch": "tsc -w",
14 | "typecheck": "tsc --noEmit"
15 | },
16 | "devDependencies": {
17 | "eslint": "^8.53.0",
18 | "eslint-define-config": "^2.0.0",
19 | "typescript": "^5.2.2",
20 | "vitest": "^0.34.6"
21 | }
22 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/hello/[name]/Hello.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use client";
3 |
4 | import Typography from "@mui/material/Typography";
5 | import { useMemo } from "react";
6 | import { kebabToTitle } from "@/utils/kebab-to-title";
7 |
8 | interface HelloProps {
9 | name: string;
10 | }
11 |
12 | export function Hello(props: HelloProps) {
13 | const { name } = props;
14 | const pascalCaseName = useMemo(() => kebabToTitle(name), [name]);
15 | return (
16 |
17 | {`Hello, ${pascalCaseName}!`}
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/packages/gboost/templates/minimal/packages/eslint-config-node/package.json.t:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@{{GB_APP_ID}}/eslint-config-node",
3 | "version": "0.1.0",
4 | "type": "module",
5 | "exports": "./.eslintrc.cjs",
6 | "devDependencies": {
7 | "@typescript-eslint/eslint-plugin": "^6.11.0",
8 | "@typescript-eslint/parser": "^6.11.0",
9 | "eslint": "^8.53.0",
10 | "eslint-config-prettier": "^9.0.0",
11 | "eslint-define-config": "^2.0.0",
12 | "eslint-plugin-prettier": "^5.0.1",
13 | "eslint-plugin-security": "^1.7.1",
14 | "prettier": "^3.1.0",
15 | "typescript": "^5.2.2"
16 | }
17 | }
--------------------------------------------------------------------------------
/docs/src/pages/_meta.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "display": "hidden",
4 | "title": "Green Boost",
5 | "theme": {
6 | "layout": "raw"
7 | }
8 | },
9 | "overview": {
10 | "title": "Overview",
11 | "type": "page"
12 | },
13 | "learn": {
14 | "title": "Learn",
15 | "type": "page"
16 | },
17 | "cli": {
18 | "title": "CLI",
19 | "type": "page"
20 | },
21 | "core": {
22 | "title": "Core",
23 | "type": "page"
24 | },
25 | "infra": {
26 | "title": "Infra",
27 | "type": "page"
28 | },
29 | "ui": {
30 | "title": "UI",
31 | "type": "page"
32 | }
33 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/core/src/entrypoints/api/handler.ts:
--------------------------------------------------------------------------------
1 | import { awsLambdaRequestHandler } from "@trpc/server/adapters/aws-lambda";
2 | import { logger } from "../../utils/logger.js";
3 | import { router } from "./router.js";
4 |
5 | export const handler = awsLambdaRequestHandler({
6 | router,
7 | onError: (opts) => logger.error("Error:", { ...opts, req: undefined }),
8 | responseMeta: () => ({
9 | headers: {
10 | // TODO: get origin of frontend (from SSM Param?) and replace *
11 | "Access-Control-Allow-Origin": "*",
12 | "Access-Control-Allow-Methods": "GET,POST", //
13 | },
14 | }),
15 | });
16 |
--------------------------------------------------------------------------------
/packages/gboost/src/create/get-template-operations/get-minimal-operations.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from "node:path";
2 | import { type Operation, OperationType } from "../operations/operations.js";
3 | import type { BaseOperationParams } from "./base-operation-params.js";
4 |
5 | export function getMinimalOperations(params: BaseOperationParams): Operation[] {
6 | const { destinationPath, templatesDirPath } = params;
7 | return [
8 | {
9 | type: OperationType.Copy,
10 | name: "CopyMinimalTemplate",
11 | sourcePath: resolve(templatesDirPath, "minimal"),
12 | destinationPath,
13 | },
14 | ];
15 | }
16 |
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/ui/src/app/goodbye/[name]/Goodbye.tsx:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | "use client";
3 |
4 | import Typography from "@mui/material/Typography";
5 | import { useMemo } from "react";
6 | import { kebabToTitle } from "@/utils/kebab-to-title";
7 |
8 | interface HelloProps {
9 | name: string;
10 | }
11 |
12 | export function Goodbye(props: HelloProps) {
13 | const { name } = props;
14 | const pascalCaseName = useMemo(() => kebabToTitle(name), [name]);
15 | return (
16 |
17 | {`Goodbye, ${pascalCaseName}!`}
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-core/ui/src/utils/decode-search-params.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import type { SearchParams } from "@{{GB_APP_ID}}/core/shared";
3 |
4 | export function decodeSearchParams(
5 | searchParams: SearchParams = {},
6 | ): SearchParams {
7 | const decodedSearchParams: SearchParams = {};
8 | for (const [key, value] of Object.entries(searchParams)) {
9 | if (Array.isArray(value)) {
10 | decodedSearchParams[key] = value.map(decodeURIComponent);
11 | } else if (value) {
12 | decodedSearchParams[key] = decodeURIComponent(value);
13 | }
14 | }
15 | return decodedSearchParams;
16 | }
17 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | extends: ["@myapp/eslint-config-react"],
7 | rules: {
8 | // @myapp/core/app-router: safe guard accidentally importing without type prefix
9 | // should only be imported from src/trpc.ts.
10 | // react-icons: only import from sub paths like react-icons/md to speed up
11 | // development server
12 | "no-restricted-imports": ["error", "@myapp/core/app-router", "react-icons"],
13 | },
14 | });
15 |
--------------------------------------------------------------------------------
/docs/src/pages/overview/contributors/intro.mdx:
--------------------------------------------------------------------------------
1 | # Contributor's Introduction
2 |
3 | Hello! Thank you for your interest in contributing to Green Boost. By contributing, you have the opportunity to scale your influence to AWS customers around the world!
4 |
5 | To get started contributing:
6 | 1. Fork the repository by clicking [here](https://github.com/awslabs/green-boost/fork)
7 | 2. Clone your forked repository like: `git clone https://github.com/bestickley/green-boost.git`
8 | 3. Change directory: `cd green-boost`
9 | 4. Install dependencies: `pnpm i`
10 | 5. Try running linting: `pnpm lint`, typechecking: `pnpm typecheck` or tests: `pnpm test`.
--------------------------------------------------------------------------------
/examples/widgets-dynamo/packages/eslint-config-react/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | // eslint-disable-next-line @typescript-eslint/no-var-requires
3 | const { defineConfig } = require("eslint-define-config");
4 |
5 | module.exports = defineConfig({
6 | root: true,
7 | extends: [
8 | "react-app", // use CRA linting rules
9 | "plugin:prettier/recommended",
10 | ],
11 | rules: {
12 | // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
13 | // reduces development bundle size speeding up dev server
14 | "no-restricted-imports": ["error", "react-icons"],
15 | },
16 | });
17 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/aspects/suppress-nags/suppress-cdk-log-retention.ts:
--------------------------------------------------------------------------------
1 | import { NagSuppressions } from "cdk-nag";
2 | import type { IConstruct } from "constructs";
3 |
4 | export function suppressCdkLogRetention(construct: IConstruct) {
5 | if (
6 | construct.node.path.match(
7 | /.+LogRetention[a-z0-9]{32}\/ServiceRole\/DefaultPolicy\/Resource$/,
8 | )
9 | ) {
10 | NagSuppressions.addResourceSuppressions(construct, [
11 | {
12 | id: "AwsSolutions-IAM5",
13 | reason:
14 | "LogRetention IAM policy requires wildcards to update log group expiration",
15 | },
16 | ]);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/aspects/suppress-nags/suppress-cdk-bucket-notifications.ts:
--------------------------------------------------------------------------------
1 | import { NagSuppressions } from "cdk-nag";
2 | import type { IConstruct } from "constructs";
3 |
4 | export function suppressCdkBucketNotifications(construct: IConstruct) {
5 | if (construct.node.path.includes("BucketNotificationsHandler")) {
6 | NagSuppressions.addResourceSuppressions(construct, [
7 | {
8 | id: "AwsSolutions-IAM5",
9 | reason:
10 | "The policy only allows the custom resource Lambda to put notifications on S3 Buckets. The CDK uses this role to avoid circular dependencies.",
11 | },
12 | ]);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "debug TS",
9 | "type": "node",
10 | "request": "launch",
11 | "runtimeExecutable": "/Users/stickb/Library/pnpm/node",
12 | "args": ["${relativeFile}"],
13 | "runtimeArgs": ["--loader", "tsx"],
14 | "skipFiles": ["/**", "node_modules/**"],
15 | "envFile": "${workspaceFolder}/.env"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/theme.ts:
--------------------------------------------------------------------------------
1 | import { createTheme as createStitchesTheme, config } from "gboost-ui";
2 | import { createTheme } from "@aws-amplify/ui-react";
3 |
4 | export const theme = createTheme({
5 | name: "base",
6 | tokens: {
7 | colors: {
8 | brand: {
9 | // add primary/secondary brand colors
10 | primary: {},
11 | secondary: {},
12 | },
13 | },
14 | },
15 | });
16 |
17 | // Temporarily need Stitches Theme until GB migrates to Vanilla Extract
18 | export const stitchesTheme = createStitchesTheme({
19 | ...config.theme,
20 | colors: {
21 | ...config.theme.colors,
22 | },
23 | });
24 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/table.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Table as CdkTable,
3 | type TableProps as CdkTableProps,
4 | } from "aws-cdk-lib/aws-dynamodb";
5 | import type { Construct } from "constructs";
6 | import { mergeDeep } from "gboost-common";
7 | import { constructDefaultProps } from "./construct-default-props.js";
8 |
9 | export type TableProps = CdkTableProps;
10 |
11 | /**
12 | * DynamoDB Table
13 | */
14 | export class Table extends CdkTable {
15 | constructor(scope: Construct, id: string, props: TableProps) {
16 | const newProps = mergeDeep(constructDefaultProps?.table, props);
17 | super(scope, id, newProps);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/infra/cdk.json:
--------------------------------------------------------------------------------
1 | {
2 | "app": "./node_modules/.bin/vite-node src/local-app.ts",
3 | "watch": {
4 | "include": [
5 | "src/**",
6 | "../core/**"
7 | ],
8 | "exclude": [
9 | "node_modules",
10 | "cdk.out",
11 | "../core/node_modules"
12 | ]
13 | },
14 | "context": {
15 | "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
16 | "@aws-cdk/core:stackRelativeExports": true,
17 | "@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
18 | "@aws-cdk/aws-lambda:recognizeVersionProps": true,
19 | "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/docs/next.config.js:
--------------------------------------------------------------------------------
1 | import createWithNextra from "nextra";
2 |
3 | const withNextra = createWithNextra({
4 | theme: "nextra-theme-docs",
5 | themeConfig: "./src/theme.config.tsx",
6 | });
7 |
8 | export default withNextra({
9 | basePath: "/green-boost",
10 | images: {
11 | unoptimized: true,
12 | },
13 | output: "export",
14 | modularizeImports: {
15 | // https://mui.com/material-ui/guides/minimizing-bundle-size/#development-environment
16 | // @mui/icons-material is automatically modularized by Next.js
17 | "@mui/material": {
18 | transform: "@mui/material/{{member}}",
19 | },
20 | },
21 | reactStrictMode: true,
22 | });
23 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/components/NavAsideLink.tsx:
--------------------------------------------------------------------------------
1 | import { NavLink } from "react-router-dom";
2 | import * as styles from "./NavAsideLink.css.js";
3 | import { clsx } from "clsx";
4 | import { ReactElement } from "react";
5 |
6 | export function NavAsideLink(
7 | props: Parameters[0]
8 | ): ReactElement {
9 | return (
10 |
12 | clsx({
13 | "amplify-flex": true,
14 | [styles.link]: true,
15 | [styles.activeLink]: isActive,
16 | })
17 | }
18 | to={props.to}
19 | >
20 | {props.children}
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/public/og-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/db/drizzle/meta/_journal.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "5",
3 | "dialect": "pg",
4 | "entries": [
5 | {
6 | "idx": 0,
7 | "version": "5",
8 | "when": 1690829406629,
9 | "tag": "0000_boring_maginty",
10 | "breakpoints": true
11 | },
12 | {
13 | "idx": 1,
14 | "version": "5",
15 | "when": 1690986344719,
16 | "tag": "0001_loud_serpent_society",
17 | "breakpoints": true
18 | },
19 | {
20 | "idx": 2,
21 | "version": "5",
22 | "when": 1691000791477,
23 | "tag": "0002_calm_mandarin",
24 | "breakpoints": true
25 | }
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/user-management/includeSelectionSetList.vtl:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2017-02-28",
3 | "operation": "Invoke",
4 | "payload": {
5 | "arguments": $utils.toJson($ctx.arguments),
6 | "identity": $utils.toJson($ctx.identity),
7 | "source": $utils.toJson($ctx.source),
8 | "result": $utils.toJson($ctx.result),
9 | "request": $utils.toJson($ctx.request),
10 | "info": {
11 | "fieldName": $utils.toJson($ctx.info.fieldName),
12 | "parentTypeName": $utils.toJson($ctx.info.parentTypeName),
13 | "selectionSetList": $utils.toJson($ctx.info.selectionSetList),
14 | "variables": $utils.toJson($ctx.info.variables)
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/packages/gboost/templates/basic-ui/core/src/config/server-config.ts:
--------------------------------------------------------------------------------
1 | import { SharedConfig } from "./shared-config";
2 | import { StageName } from "./stage-name";
3 |
4 | /**
5 | * Config used only on server
6 | */
7 | export class ServerConfig extends SharedConfig {
8 | /**
9 | * Environment variable names. No [magic strings](https://deviq.com/antipatterns/magic-strings)!
10 | */
11 | static envVarNames = {
12 | STAGE_NAME: "STAGE_NAME",
13 | };
14 |
15 | constructor(stageName?: string) {
16 | super(stageName || StageName.Local);
17 | }
18 | }
19 |
20 | export const serverConfig = new ServerConfig(
21 | process.env[ServerConfig.envVarNames.STAGE_NAME],
22 | );
23 |
--------------------------------------------------------------------------------
/packages/gboost/src/create/operations/operations.ts:
--------------------------------------------------------------------------------
1 | import type { CopyOperation } from "./copy.js";
2 | import type { ReplaceOperation } from "./replace.js";
3 | import type { RenameFilesOperation } from "./rename-files.js";
4 | import type { UpdatePackageJsonOperation } from "./update-package-json.js";
5 |
6 | export { OperationType } from "./common.js";
7 | export type Operation =
8 | | CopyOperation
9 | | ReplaceOperation
10 | | UpdatePackageJsonOperation
11 | | RenameFilesOperation;
12 |
13 | export { copy } from "./copy.js";
14 | export { replace } from "./replace.js";
15 | export { updatePackageJson } from "./update-package-json.js";
16 | export { renameFiles } from "./rename-files.js";
17 |
--------------------------------------------------------------------------------
/packages/gboost/templates/crud-postgres/core/src/adapters/secondary/db-adapter.ts:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | import { drizzle } from "drizzle-orm/postgres-js";
3 | import { item } from "../../modules/item/item.db";
4 | import type { DrizzleConfig } from "drizzle-orm";
5 | import { sqlRead, sqlWrite } from "../../db/config";
6 |
7 | const schema = {
8 | item,
9 | };
10 | const drizzleConfig: DrizzleConfig = {
11 | logger: process.env["NODE_ENV"] !== "production",
12 | schema,
13 | };
14 |
15 | /**
16 | * DB Write Instance
17 | */
18 | export const dbWrite = drizzle(sqlWrite, drizzleConfig);
19 |
20 | /**
21 | * DB Reader Instance
22 | *
23 | */
24 | export const dbRead = drizzle(sqlRead, drizzleConfig);
25 |
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/src/components/Header.tsx:
--------------------------------------------------------------------------------
1 | import { Dispatch, ReactElement, SetStateAction } from "react";
2 | import { Header as GbHeader } from "gboost-ui";
3 | import { Heading } from "@aws-amplify/ui-react";
4 | import { Link } from "react-router-dom";
5 |
6 | interface HeaderProps {
7 | open: boolean;
8 | setOpen: Dispatch>;
9 | }
10 |
11 | export function Header(props: HeaderProps): ReactElement {
12 | const { open, setOpen } = props;
13 | return (
14 |
17 | Widgets
18 |
19 | }
20 | open={open}
21 | setOpen={setOpen}
22 | />
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/docs/public/green-boost-gradient.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/user-management/function/getCognitoIdentity.ts:
--------------------------------------------------------------------------------
1 | import type { AppSyncIdentityCognito, AppSyncResolverEvent } from "aws-lambda";
2 |
3 | // create custom type so consumer doesn't have to assert groups exist
4 | interface AppSyncIdentityCognitoCustom extends AppSyncIdentityCognito {
5 | groups: string[];
6 | }
7 |
8 | export function getCognitoIdentity(
9 | e: AppSyncResolverEvent,
10 | ): AppSyncIdentityCognitoCustom {
11 | const identity = e.identity as AppSyncIdentityCognitoCustom;
12 | if (identity?.groups !== null) {
13 | return identity;
14 | } else {
15 | throw new Error(
16 | "AppSyncResolverEvent does not have cognito identity with groups",
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/gboost-infra/src/static-site/response-headers.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, test, expect } from "vitest";
2 | import { getCsp, getCspSource } from "./response-headers.js";
3 |
4 | describe("getCspSource", () => {
5 | test("CSP sources are properly quoted and spaced", () => {
6 | expect(getCspSource(["none", "self", "https://google.com"])).toBe(
7 | "'none' 'self' https://google.com",
8 | );
9 | });
10 | });
11 |
12 | describe("getCsp", () => {
13 | test("default csp", () => {
14 | const result = getCsp({});
15 | expect(result).toBe(
16 | "default-src 'self'; form-action 'none'; navigate-to 'none'; object-src 'none';",
17 | );
18 | });
19 | });
20 |
21 | // TODO add tests for other functions
22 |
--------------------------------------------------------------------------------
/docs/src/pages/overview/quick-start.mdx:
--------------------------------------------------------------------------------
1 | # Quick Start
2 |
3 | 1. Follow the [prerequisites](./prereqs).
4 | 2. Install the Green Boost CLI: `pnpm add -g gboost`.
5 | 3. Create a web app with: `gboost create`.
6 | 4. Follow the prompts to select a template, directory, app id, and app title. To learn more about `gboost create` and the templates available, learn more [here](../cli/create).
7 | 5. Change directory into your directory: `cd `
8 | 6. Install dependencies: `pnpm i`.
9 | 7. Change directory into the infrastructure folder: `cd infra`
10 | 8. Deploy: `pnpm deploy:local`
11 | 9. View your web app the CloudFront URL printed in your terminal towards the end of output from the previous command.
12 | 10. Clean up: `pnpm destroy:local`.
--------------------------------------------------------------------------------
/examples/widgets-dynamo/ui/public/favicon-16x16.png:
--------------------------------------------------------------------------------
1 | �PNG
2 |
3 |
IHDR (-S gAMA ���a cHRM z&