├── e2e
├── .gitignore
├── .eslintrc
├── jest.config.js
├── system-db.ts
├── 9-cleaning
│ └── 00-clean.test.ts
├── package.json
├── tsconfig.json
└── jest-sequencer.js
├── web
├── src
│ ├── utils
│ │ ├── .gitkeep
│ │ ├── getAvatarUrl.ts
│ │ ├── getRegionById.ts
│ │ └── getPageInfo.ts
│ ├── constants
│ │ └── .gitkeep
│ ├── vite-env.d.ts
│ ├── types
│ │ └── index.d.ts
│ ├── components
│ │ ├── DateRangePicker
│ │ │ └── index.css
│ │ ├── EditableTable
│ │ │ └── index.module.scss
│ │ ├── Content
│ │ │ └── index.tsx
│ │ ├── Markdown
│ │ │ └── formatLinkText.ts
│ │ ├── IconText
│ │ │ ├── index.module.scss
│ │ │ └── index.tsx
│ │ ├── DependenceList
│ │ │ └── index.module.scss
│ │ ├── Editor
│ │ │ └── index.scss
│ │ ├── Panel
│ │ │ ├── index.module.scss
│ │ │ └── index.tsx
│ │ ├── TextButton
│ │ │ └── index.tsx
│ │ ├── SectionList
│ │ │ └── index.module.scss
│ │ ├── FileUpload
│ │ │ └── index.module.scss
│ │ └── ColorModeSwitch
│ │ │ └── index.tsx
│ ├── pages
│ │ ├── app
│ │ │ ├── setting
│ │ │ │ ├── index.css
│ │ │ │ ├── UserSetting
│ │ │ │ │ ├── CardRedemption
│ │ │ │ │ │ └── service.ts
│ │ │ │ │ └── PATList
│ │ │ │ │ │ └── DateSelector
│ │ │ │ │ │ └── index.module.scss
│ │ │ │ └── SysSetting
│ │ │ │ │ └── AppEnvList
│ │ │ │ │ └── EditTextarea
│ │ │ │ │ └── index.tsx
│ │ │ ├── functions
│ │ │ │ └── mods
│ │ │ │ │ ├── FunctionPanel
│ │ │ │ │ ├── index.css
│ │ │ │ │ └── ContextMenu
│ │ │ │ │ │ └── index.scss
│ │ │ │ │ └── HeadPanel
│ │ │ │ │ └── index.css
│ │ │ ├── storages
│ │ │ │ └── mods
│ │ │ │ │ └── index.module.scss
│ │ │ ├── database
│ │ │ │ ├── CollectionDataList
│ │ │ │ │ └── mods
│ │ │ │ │ │ ├── DataPanel
│ │ │ │ │ │ └── index.module.scss
│ │ │ │ │ │ └── ColPanel
│ │ │ │ │ │ └── index.tsx
│ │ │ │ ├── mods
│ │ │ │ │ └── AddRulesModal
│ │ │ │ │ │ └── policyTemplate.ts
│ │ │ │ └── BottomPanel
│ │ │ │ │ └── index.tsx
│ │ │ └── mods
│ │ │ │ └── SideBar
│ │ │ │ └── index.module.scss
│ │ ├── homepage
│ │ │ ├── video.tsx
│ │ │ ├── status.module.scss
│ │ │ ├── homepage.css
│ │ │ ├── circle.tsx
│ │ │ ├── contact.tsx
│ │ │ ├── status.tsx
│ │ │ └── index.tsx
│ │ └── home
│ │ │ ├── mods
│ │ │ ├── Empty
│ │ │ │ └── index.module.scss
│ │ │ └── CreateAppModal
│ │ │ │ ├── RuntimeItem
│ │ │ │ └── index.tsx
│ │ │ │ └── BundleItem
│ │ │ │ └── index.tsx
│ │ │ └── service.ts
│ ├── layouts
│ │ └── Auth
│ │ │ └── index.module.scss
│ ├── hooks
│ │ ├── useDB.ts
│ │ └── useCustomToast.ts
│ └── apis
│ │ └── dependence.ts
├── .env.production
├── public
│ ├── robots.txt
│ ├── bg.png
│ ├── logo.png
│ ├── favicon.ico
│ ├── logo_light.png
│ ├── logo_text.png
│ ├── pwa-64x64.png
│ ├── homepage
│ │ ├── bg.png
│ │ ├── p1.png
│ │ ├── p2.png
│ │ ├── p3.png
│ │ ├── p4.png
│ │ ├── p5.png
│ │ ├── banner.png
│ │ ├── database.png
│ │ ├── function.png
│ │ ├── icon_06.png
│ │ ├── laficon.jpg
│ │ ├── logo_text.png
│ │ ├── storage.png
│ │ ├── videobg.png
│ │ ├── videomobile.png
│ │ ├── Vector.svg
│ │ ├── icon_02.svg
│ │ ├── logo_icon.svg
│ │ ├── icon_03.svg
│ │ ├── icon_05.svg
│ │ ├── cancel_btn.svg
│ │ └── play.svg
│ ├── masked-icon.png
│ ├── pwa-192x192.png
│ ├── pwa-512x512.png
│ ├── apple-touch-icon.png
│ ├── fonts
│ │ └── NotoSansSC-Medium.ttf
│ └── js
│ │ └── monaco-editor.0.43.0
│ │ └── base
│ │ ├── browser
│ │ └── ui
│ │ │ └── codicons
│ │ │ └── codicon
│ │ │ └── codicon.ttf
│ │ └── common
│ │ └── worker
│ │ └── simpleWorker.nls.js
├── .dockerignore
├── .stylelintrc.json
├── .eslintrc
├── Dockerfile
├── postcss.config.cjs
├── tsconfig.node.json
├── .env
├── .swagger.config.js
├── .gitignore
└── index.html
├── docs
├── .eslintignore
├── en
│ ├── architecture.md
│ └── ide.png
├── public
│ ├── CNAME
│ └── logo.png
├── .gitignore
├── .eslintrc
├── zh
│ ├── doc-images
│ │ ├── db.png
│ │ ├── AppID.png
│ │ ├── file.png
│ │ ├── index.png
│ │ ├── mj-id.png
│ │ ├── add-env.png
│ │ ├── add-pat.png
│ │ ├── appList.png
│ │ ├── dblist.jpg
│ │ ├── doc-db.png
│ │ ├── upload.png
│ │ ├── Laf-Pilot.png
│ │ ├── Laf-Pilot2.png
│ │ ├── add-polocy.png
│ │ ├── app-list.png
│ │ ├── bind-pay.png
│ │ ├── bind-pay2.png
│ │ ├── cli-mind.png
│ │ ├── doc-policy.png
│ │ ├── function.png
│ │ ├── new-logs-1.jpg
│ │ ├── old-logs.jpg
│ │ ├── register.png
│ │ ├── todo-demo.png
│ │ ├── SALAI_TOKEN.jpg
│ │ ├── add-packages.png
│ │ ├── auto-build1.png
│ │ ├── auto-build2.png
│ │ ├── creat-polocy.png
│ │ ├── creat-token.png
│ │ ├── doc-app-list.png
│ │ ├── doc-storage.png
│ │ ├── function-log.png
│ │ ├── function-url.png
│ │ ├── my-template.png
│ │ ├── open-website.png
│ │ ├── oss-get-sts.png
│ │ ├── package-list.png
│ │ ├── pakcage-list.jpg
│ │ ├── use-injector.png
│ │ ├── add-env-step1.png
│ │ ├── add-env-step2.png
│ │ ├── add-env-step3.png
│ │ ├── create-bucket-1.png
│ │ ├── create-bucket.png
│ │ ├── create-function.jpg
│ │ ├── create-function.png
│ │ ├── create-gather.png
│ │ ├── create-injector.png
│ │ ├── create-laf-app.jpg
│ │ ├── delete-package.png
│ │ ├── function-body.png
│ │ ├── function-market.png
│ │ ├── function-query.png
│ │ ├── polocy-db-data.png
│ │ ├── set-wechat-pay.png
│ │ ├── slack-connect.jpg
│ │ ├── specification.jpg
│ │ ├── web-ide-index.png
│ │ ├── website-hosting.png
│ │ ├── application-list.png
│ │ ├── doc-function-list.png
│ │ ├── function-template.png
│ │ ├── run-cloudfunction.png
│ │ ├── slack-create-app.jpg
│ │ ├── slack-install-bot.jpg
│ │ ├── create-application.png
│ │ ├── create-cloudfunction.png
│ │ ├── edit-cloudfunction.png
│ │ ├── getToken-parseToken.png
│ │ ├── slack-connect-create.jpg
│ │ ├── slack-create-app-bot.jpg
│ │ ├── change-package-version.png
│ │ ├── publish-cloudfunction.png
│ │ ├── sealos-website-hosting.png
│ │ ├── select-package-version.png
│ │ ├── slack-connect-create-1.jpg
│ │ ├── MediaPlatformBaseSetting.png
│ │ └── MediaPlatformBaseSetting2.png
│ ├── overview-ide.png
│ ├── cloud-function
│ │ ├── env.png
│ │ ├── cron.png
│ │ └── cron.md
│ ├── cloud-database
│ │ ├── collection.png
│ │ └── database-ql
│ │ │ ├── dblist.jpg
│ │ │ └── del.md
│ ├── cloud-storage
│ │ ├── website-hosting-0.png
│ │ ├── website-hosting-domain.png
│ │ ├── delete.md
│ │ └── website-hosting.md
│ └── examples
│ │ └── index.md
├── Dockerfile
├── .vitepress
│ ├── theme
│ │ ├── index.ts
│ │ └── custom.css
│ └── en.mts
└── scripts
│ └── check-version.js
├── runtimes
├── python
│ └── TBD.md
└── nodejs
│ ├── .eslintrc
│ ├── .gitignore
│ ├── src
│ ├── support
│ │ ├── engine
│ │ │ └── index.ts
│ │ ├── types.ts
│ │ ├── logger.ts
│ │ ├── database-change-stream
│ │ │ └── website-hosting-change-stream.ts
│ │ └── init-hook.ts
│ └── constants.ts
│ ├── .dockerignore
│ ├── Dockerfile.init
│ ├── functions
│ └── tsconfig.json
│ ├── start.sh
│ ├── build-image.sh
│ └── Dockerfile
├── server
├── src
│ ├── i18n
│ │ ├── en
│ │ │ ├── subscription.json
│ │ │ ├── notification.json
│ │ │ └── function.json
│ │ ├── zh
│ │ │ ├── subscription.json
│ │ │ ├── notification.json
│ │ │ └── function.json
│ │ └── zh-CN
│ │ │ ├── subscription.json
│ │ │ ├── notification.json
│ │ │ └── function.json
│ ├── app.service.ts
│ ├── notification
│ │ ├── notification-type.ts
│ │ ├── notification.module.ts
│ │ └── entities
│ │ │ └── notification.ts
│ ├── storage
│ │ ├── minio
│ │ │ └── types.ts
│ │ ├── entities
│ │ │ ├── minio.ts
│ │ │ ├── storage-user.ts
│ │ │ └── storage-bucket.ts
│ │ └── dto
│ │ │ ├── update-bucket.dto.ts
│ │ │ └── create-bucket.dto.ts
│ ├── database
│ │ ├── entities
│ │ │ ├── database-sync-record.ts
│ │ │ └── collection.ts
│ │ ├── dto
│ │ │ ├── update-dedicated-database.dto.ts
│ │ │ ├── update-policy.dto.ts
│ │ │ ├── create-policy.dto.ts
│ │ │ ├── update-rule.dto.ts
│ │ │ ├── import-database.dto.ts
│ │ │ ├── create-collection.dto.ts
│ │ │ ├── update-collection.dto.ts
│ │ │ ├── create-rule.dto.ts
│ │ │ ├── update-dedicated-database-state.dto.ts
│ │ │ └── create-dedicated-database.dto.ts
│ │ └── listeners
│ │ │ └── application.listener.ts
│ ├── group
│ │ ├── group-role.decorator.ts
│ │ ├── dto
│ │ │ ├── create-group.dto.ts
│ │ │ ├── update-group.dto.ts
│ │ │ ├── update-group-member-role.dto.ts
│ │ │ ├── find-group-member.dto.ts
│ │ │ ├── find-group-invite-code.dto.ts
│ │ │ ├── update-group-invite-code.dto.ts
│ │ │ └── get-group-invite-code-detail.dto.ts
│ │ └── entities
│ │ │ ├── group-application.ts
│ │ │ ├── group.ts
│ │ │ ├── group-invite-code.ts
│ │ │ └── group-member.ts
│ ├── user
│ │ ├── dto
│ │ │ ├── update-avatar.dto.ts
│ │ │ ├── bind-username.dto.ts
│ │ │ ├── bind-email.dto.ts
│ │ │ └── create-pat.dto.ts
│ │ ├── entities
│ │ │ ├── user-avatar.ts
│ │ │ ├── user-password.ts
│ │ │ ├── pat.ts
│ │ │ ├── user.ts
│ │ │ ├── user-profile.ts
│ │ │ └── user-quota.ts
│ │ └── user.module.ts
│ ├── recycle-bin
│ │ ├── entities
│ │ │ └── recycle-bin.ts
│ │ └── cloud-function
│ │ │ ├── interface
│ │ │ └── function-recycle-bin-query.interface.ts
│ │ │ └── dto
│ │ │ ├── delete-recycle-bin-functions.dto.ts
│ │ │ └── restore-recycle-bin-functions.dto.ts
│ ├── authentication
│ │ ├── jwt.auth.guard.ts
│ │ ├── dto
│ │ │ ├── github-signin.dto.ts
│ │ │ ├── github-jump-login.dto.ts
│ │ │ ├── pat2token.dto.ts
│ │ │ ├── passwd-check.dto.ts
│ │ │ ├── github-bind.dto.ts
│ │ │ ├── email-verify-code.dto.ts
│ │ │ ├── send-email-code.dto.ts
│ │ │ ├── passwd-signin.dto.ts
│ │ │ └── send-phone-code.dto.ts
│ │ └── entities
│ │ │ ├── auth-provider.ts
│ │ │ ├── types.ts
│ │ │ ├── email-verify-code.ts
│ │ │ └── sms-verify-code.ts
│ ├── billing
│ │ ├── interface
│ │ │ └── billing-query.interface.ts
│ │ ├── dto
│ │ │ └── billings.dto.ts
│ │ └── entities
│ │ │ └── network-traffic.ts
│ ├── trigger
│ │ ├── dto
│ │ │ ├── update-trigger.dto.ts
│ │ │ └── create-trigger.dto.ts
│ │ └── entities
│ │ │ └── cron-trigger.ts
│ ├── initializer
│ │ ├── deploy-manifest
│ │ │ ├── databaseOpsRequestStart.yaml
│ │ │ ├── databaseOpsRequestStop.yaml
│ │ │ ├── databaseOpsRequestRestart.yaml
│ │ │ ├── databaseOpsRequestHorizontalScaling.yaml
│ │ │ ├── databaseOpsRequestVolumeExpansion.yaml
│ │ │ └── databaseOpsRequestVerticalScaling.yaml
│ │ └── initializer.module.ts
│ ├── function-template
│ │ ├── dto
│ │ │ ├── function-template-usedBy.dto.ts
│ │ │ └── use-function-template.dto.ts
│ │ └── function-template.module.ts
│ ├── utils
│ │ ├── crypto.ts
│ │ ├── interface.ts
│ │ └── decorator.ts
│ ├── website
│ │ ├── dto
│ │ │ ├── update-website.dto.ts
│ │ │ └── create-website.dto.ts
│ │ ├── website.module.ts
│ │ └── entities
│ │ │ └── website.ts
│ ├── dependency
│ │ ├── dto
│ │ │ ├── delete-dependency.dto.ts
│ │ │ ├── create-dependency.dto.ts
│ │ │ └── update-dependency.dto.ts
│ │ └── dependency.module.ts
│ ├── account
│ │ ├── interface
│ │ │ └── account-query.interface.ts
│ │ ├── entities
│ │ │ ├── account-gift-code.ts
│ │ │ ├── account-charge-reward.ts
│ │ │ ├── payment-channel.ts
│ │ │ ├── account-transaction.ts
│ │ │ └── account.ts
│ │ ├── dto
│ │ │ ├── use-gift-code.dto.ts
│ │ │ └── invite-code.dto.ts
│ │ └── account.module.ts
│ ├── function
│ │ ├── dto
│ │ │ ├── update-function-debug.dto.ts
│ │ │ └── compile-function.dto.ts
│ │ ├── entities
│ │ │ └── cloud-function-history.ts
│ │ └── function.module.ts
│ ├── setting
│ │ ├── setting.module.ts
│ │ └── setting.service.ts
│ ├── interceptor
│ │ ├── interceptor.module.ts
│ │ └── dto
│ │ │ └── http-interceptor.dto.ts
│ ├── application
│ │ ├── dto
│ │ │ ├── create-env.dto.ts
│ │ │ ├── pod.dto.ts
│ │ │ └── create-application.dto.ts
│ │ ├── events
│ │ │ ├── application-creating.event.ts
│ │ │ └── application-bundle-updating.event.ts
│ │ ├── bundle.service.ts
│ │ └── entities
│ │ │ └── runtime.ts
│ ├── region
│ │ ├── region.module.ts
│ │ ├── cluster
│ │ │ └── cluster.service.spec.ts
│ │ └── region.controller.ts
│ ├── log
│ │ ├── entities
│ │ │ └── function-log.ts
│ │ └── log.module.ts
│ ├── gateway
│ │ └── entities
│ │ │ └── bucket-domain.ts
│ ├── monitor
│ │ └── monitor.module.ts
│ ├── instance
│ │ └── instance.module.ts
│ ├── app.controller.ts
│ └── generated
│ │ └── i18n.generated.ts
├── .dockerignore
├── .eslintrc
├── tsconfig.build.json
├── build-image.sh
├── test
│ ├── jest-e2e.json
│ └── app.e2e-spec.ts
├── nest-cli.json
├── .gitignore
└── tsconfig.json
├── cli
├── .npmignore
├── .eslintrc
├── template
│ ├── gitignore
│ └── package.json
└── src
│ ├── util
│ ├── print.ts
│ ├── sys.ts
│ └── format.ts
│ ├── action
│ ├── policy
│ │ └── dto.ts
│ ├── storage
│ │ └── s3.ts
│ └── environment
│ │ └── index.ts
│ ├── common
│ ├── prompts.ts
│ ├── wait.ts
│ └── hook.ts
│ ├── api
│ ├── pat.ts
│ ├── custom.ts
│ └── v1
│ │ └── monitor.ts
│ └── command
│ ├── deploy
│ └── index.ts
│ ├── application
│ └── index.ts
│ ├── environment
│ └── index.ts
│ └── database
│ └── index.ts
├── packages
├── client-sdk
│ ├── .npmignore
│ ├── .eslintrc
│ ├── src
│ │ ├── request
│ │ │ └── index.ts
│ │ └── index-bundle.ts
│ ├── tests
│ │ ├── http
│ │ │ ├── config.js
│ │ │ ├── read_test.js
│ │ │ └── add_test.js
│ │ └── units
│ │ │ └── cloud_test.js
│ └── webpack.config.js
├── cloud-sdk
│ ├── .npmignore
│ ├── .eslintrc
│ ├── src
│ │ ├── util.ts
│ │ └── index.ts
│ └── README.md
├── database-ql
│ ├── .npmignore
│ ├── .eslintrc
│ ├── src
│ │ ├── geo
│ │ │ ├── index.ts
│ │ │ └── interface.ts
│ │ └── serverDate
│ │ │ └── index.ts
│ └── tests
│ │ └── units
│ │ └── get
│ │ ├── orderby.test.js
│ │ └── page.test.js
├── database-proxy
│ ├── .eslintrc
│ ├── src
│ │ ├── policy
│ │ │ └── index.ts
│ │ ├── accessor
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── dbi
│ │ │ ├── index.ts
│ │ │ └── request.ts
│ │ └── validators
│ │ │ ├── index.ts
│ │ │ └── lookup
│ │ │ └── index.ts
│ ├── .npmignore
│ ├── docs
│ │ ├── todo.md
│ │ ├── ruler_v2_design.md
│ │ └── rules-v2.json
│ └── tests
│ │ ├── units
│ │ ├── policy
│ │ │ └── rules.json
│ │ └── accessor.test.js
│ │ ├── mongo_db
│ │ └── _db.js
│ │ └── mysql_db
│ │ └── _db.js
├── eslint-config-laf
│ ├── .eslintrc
│ ├── docs.js
│ ├── service.js
│ ├── test.js
│ ├── runtime.js
│ ├── cli.js
│ └── server.js
├── node-modules-utils
│ ├── .eslintrc
│ ├── src
│ │ └── index.ts
│ ├── copy2app.sh
│ ├── README.md
│ └── tests
│ │ ├── cloud-sdk.test.js
│ │ └── import.test.js
└── run-tests.sh
├── services
└── runtime-exporter
│ ├── .eslintrc
│ ├── .gitignore
│ ├── Dockerfile
│ ├── src
│ └── logger.ts
│ ├── tsconfig.json
│ └── tsconfig.dev.json
├── .husky
└── pre-commit
├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ └── config.yml
├── no-response.yml
├── stale.yml
├── actions
│ └── build-docs
│ │ └── action.yml
├── gh-bot.yml
├── FUNDING.yml
└── workflows
│ └── build-scripts-updated.yml
├── .vscode
└── extensions.json
├── .lycheeignore
├── lerna.json
└── .gitignore
/e2e/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 |
--------------------------------------------------------------------------------
/web/src/utils/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/.eslintignore:
--------------------------------------------------------------------------------
1 | public
--------------------------------------------------------------------------------
/web/src/constants/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/en/architecture.md:
--------------------------------------------------------------------------------
1 |
2 | > TBD
--------------------------------------------------------------------------------
/docs/public/CNAME:
--------------------------------------------------------------------------------
1 | lafjs.github.io
--------------------------------------------------------------------------------
/runtimes/python/TBD.md:
--------------------------------------------------------------------------------
1 |
2 | > TBD
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
3 | .vitepress/cache
--------------------------------------------------------------------------------
/server/src/i18n/en/subscription.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/server/src/i18n/zh/subscription.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/web/.env.production:
--------------------------------------------------------------------------------
1 | VITE_SERVER_BASE_URL=
--------------------------------------------------------------------------------
/server/.dockerignore:
--------------------------------------------------------------------------------
1 |
2 | .env.local
3 | .env
--------------------------------------------------------------------------------
/server/src/i18n/zh-CN/subscription.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/web/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Allow: /
--------------------------------------------------------------------------------
/web/.dockerignore:
--------------------------------------------------------------------------------
1 | # node_modules
2 | .env.local
3 | .env
--------------------------------------------------------------------------------
/cli/.npmignore:
--------------------------------------------------------------------------------
1 | ./node_modules
2 | .DS_Store
3 | src
4 | tests
--------------------------------------------------------------------------------
/web/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/cli/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/cli"
4 | }
--------------------------------------------------------------------------------
/e2e/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/test"
4 | }
--------------------------------------------------------------------------------
/web/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | { "extends": ["stylelint-config-standard"] }
--------------------------------------------------------------------------------
/docs/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/docs"
4 | }
--------------------------------------------------------------------------------
/server/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/server"
4 | }
--------------------------------------------------------------------------------
/web/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/web"
4 | }
5 |
--------------------------------------------------------------------------------
/docs/en/ide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/en/ide.png
--------------------------------------------------------------------------------
/packages/client-sdk/.npmignore:
--------------------------------------------------------------------------------
1 | ./node_modules
2 | .DS_Store
3 | src
4 | tests
--------------------------------------------------------------------------------
/packages/cloud-sdk/.npmignore:
--------------------------------------------------------------------------------
1 | ./node_modules
2 | .DS_Store
3 | src
4 | tests
--------------------------------------------------------------------------------
/web/src/types/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module "vscode/service-override/files";
2 |
--------------------------------------------------------------------------------
/packages/database-ql/.npmignore:
--------------------------------------------------------------------------------
1 | ./node_modules
2 | .DS_Store
3 | ./src
4 | ./tests
--------------------------------------------------------------------------------
/runtimes/nodejs/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/runtime"
4 | }
--------------------------------------------------------------------------------
/web/public/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/bg.png
--------------------------------------------------------------------------------
/cli/template/gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .app.yaml
3 | package-lock.json
4 | laf.yaml
5 |
--------------------------------------------------------------------------------
/docs/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/public/logo.png
--------------------------------------------------------------------------------
/packages/client-sdk/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/package"
4 | }
--------------------------------------------------------------------------------
/packages/cloud-sdk/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/package"
4 | }
--------------------------------------------------------------------------------
/packages/database-ql/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/package"
4 | }
--------------------------------------------------------------------------------
/web/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/logo.png
--------------------------------------------------------------------------------
/packages/cloud-sdk/src/util.ts:
--------------------------------------------------------------------------------
1 | export const IS_SEALAF = process.env.IS_SEALAF === 'true'
2 |
--------------------------------------------------------------------------------
/packages/database-proxy/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/package"
4 | }
--------------------------------------------------------------------------------
/services/runtime-exporter/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/service"
4 | }
--------------------------------------------------------------------------------
/web/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/favicon.ico
--------------------------------------------------------------------------------
/docs/zh/doc-images/db.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/db.png
--------------------------------------------------------------------------------
/docs/zh/overview-ide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/overview-ide.png
--------------------------------------------------------------------------------
/packages/eslint-config-laf/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "./package.js"
4 | }
--------------------------------------------------------------------------------
/packages/eslint-config-laf/docs.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: './package.js',
3 | }
4 |
--------------------------------------------------------------------------------
/packages/eslint-config-laf/service.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: './server.js',
3 | }
4 |
--------------------------------------------------------------------------------
/packages/eslint-config-laf/test.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: './package.js',
3 | }
4 |
--------------------------------------------------------------------------------
/packages/node-modules-utils/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": "laf/package"
4 | }
--------------------------------------------------------------------------------
/services/runtime-exporter/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | .env
4 | tsconfig.build.json
5 |
--------------------------------------------------------------------------------
/web/public/logo_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/logo_light.png
--------------------------------------------------------------------------------
/web/public/logo_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/logo_text.png
--------------------------------------------------------------------------------
/web/public/pwa-64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/pwa-64x64.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/AppID.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/AppID.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/file.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/index.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/mj-id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/mj-id.png
--------------------------------------------------------------------------------
/web/public/homepage/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/bg.png
--------------------------------------------------------------------------------
/web/public/homepage/p1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/p1.png
--------------------------------------------------------------------------------
/web/public/homepage/p2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/p2.png
--------------------------------------------------------------------------------
/web/public/homepage/p3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/p3.png
--------------------------------------------------------------------------------
/web/public/homepage/p4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/p4.png
--------------------------------------------------------------------------------
/web/public/homepage/p5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/p5.png
--------------------------------------------------------------------------------
/web/public/masked-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/masked-icon.png
--------------------------------------------------------------------------------
/web/public/pwa-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/pwa-192x192.png
--------------------------------------------------------------------------------
/web/public/pwa-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/pwa-512x512.png
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npm run lint-staged
5 |
--------------------------------------------------------------------------------
/docs/zh/cloud-function/env.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/cloud-function/env.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/add-env.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/add-env.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/add-pat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/add-pat.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/appList.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/appList.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/dblist.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/dblist.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/doc-db.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/doc-db.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/upload.png
--------------------------------------------------------------------------------
/packages/database-proxy/src/policy/index.ts:
--------------------------------------------------------------------------------
1 | export * from './interface'
2 | export * from './policy'
3 |
--------------------------------------------------------------------------------
/web/public/homepage/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/banner.png
--------------------------------------------------------------------------------
/docs/zh/cloud-function/cron.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/cloud-function/cron.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/Laf-Pilot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/Laf-Pilot.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/Laf-Pilot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/Laf-Pilot2.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/add-polocy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/add-polocy.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/app-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/app-list.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/bind-pay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/bind-pay.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/bind-pay2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/bind-pay2.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/cli-mind.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/cli-mind.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/doc-policy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/doc-policy.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/function.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/function.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/new-logs-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/new-logs-1.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/old-logs.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/old-logs.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/register.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/register.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/todo-demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/todo-demo.png
--------------------------------------------------------------------------------
/web/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/web/public/homepage/database.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/database.png
--------------------------------------------------------------------------------
/web/public/homepage/function.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/function.png
--------------------------------------------------------------------------------
/web/public/homepage/icon_06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/icon_06.png
--------------------------------------------------------------------------------
/web/public/homepage/laficon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/laficon.jpg
--------------------------------------------------------------------------------
/web/public/homepage/logo_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/logo_text.png
--------------------------------------------------------------------------------
/web/public/homepage/storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/storage.png
--------------------------------------------------------------------------------
/web/public/homepage/videobg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/videobg.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/SALAI_TOKEN.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/SALAI_TOKEN.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/add-packages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/add-packages.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/auto-build1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/auto-build1.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/auto-build2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/auto-build2.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/creat-polocy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/creat-polocy.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/creat-token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/creat-token.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/doc-app-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/doc-app-list.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/doc-storage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/doc-storage.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/function-log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/function-log.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/function-url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/function-url.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/my-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/my-template.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/open-website.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/open-website.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/oss-get-sts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/oss-get-sts.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/package-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/package-list.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/pakcage-list.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/pakcage-list.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/use-injector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/use-injector.png
--------------------------------------------------------------------------------
/web/public/homepage/videomobile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/homepage/videomobile.png
--------------------------------------------------------------------------------
/docs/zh/cloud-database/collection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/cloud-database/collection.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/add-env-step1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/add-env-step1.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/add-env-step2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/add-env-step2.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/add-env-step3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/add-env-step3.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-bucket-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-bucket-1.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-bucket.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-bucket.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-function.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-function.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-function.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-function.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-gather.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-gather.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-injector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-injector.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-laf-app.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-laf-app.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/delete-package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/delete-package.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/function-body.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/function-body.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/function-market.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/function-market.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/function-query.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/function-query.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/polocy-db-data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/polocy-db-data.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/set-wechat-pay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/set-wechat-pay.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/slack-connect.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/slack-connect.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/specification.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/specification.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/web-ide-index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/web-ide-index.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/website-hosting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/website-hosting.png
--------------------------------------------------------------------------------
/web/public/fonts/NotoSansSC-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/fonts/NotoSansSC-Medium.ttf
--------------------------------------------------------------------------------
/docs/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM bitnami/openresty:latest
2 |
3 | WORKDIR /app
4 | EXPOSE 8080
5 |
6 | ADD ./.vitepress/dist /app/
7 |
--------------------------------------------------------------------------------
/docs/zh/doc-images/application-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/application-list.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/doc-function-list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/doc-function-list.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/function-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/function-template.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/run-cloudfunction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/run-cloudfunction.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/slack-create-app.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/slack-create-app.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/slack-install-bot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/slack-install-bot.jpg
--------------------------------------------------------------------------------
/server/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common'
2 |
3 | @Injectable()
4 | export class AppService {}
5 |
--------------------------------------------------------------------------------
/docs/zh/cloud-storage/website-hosting-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/cloud-storage/website-hosting-0.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-application.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-application.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/create-cloudfunction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/create-cloudfunction.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/edit-cloudfunction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/edit-cloudfunction.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/getToken-parseToken.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/getToken-parseToken.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/slack-connect-create.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/slack-connect-create.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/slack-create-app-bot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/slack-create-app-bot.jpg
--------------------------------------------------------------------------------
/packages/database-proxy/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | .nyc_output
4 | .DS_Store
5 | DS_Store
6 | src
7 | tests
8 | docs
--------------------------------------------------------------------------------
/web/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:alpine
2 |
3 | COPY ./nginx.conf /etc/nginx/conf.d/default.conf
4 | COPY ./dist /usr/share/nginx/html
5 |
--------------------------------------------------------------------------------
/web/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/docs/.vitepress/theme/index.ts:
--------------------------------------------------------------------------------
1 | import DefaultTheme from 'vitepress/theme'
2 | import './custom.css'
3 |
4 | export default DefaultTheme
--------------------------------------------------------------------------------
/docs/zh/cloud-database/database-ql/dblist.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/cloud-database/database-ql/dblist.jpg
--------------------------------------------------------------------------------
/docs/zh/doc-images/change-package-version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/change-package-version.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/publish-cloudfunction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/publish-cloudfunction.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/sealos-website-hosting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/sealos-website-hosting.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/select-package-version.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/select-package-version.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/slack-connect-create-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/slack-connect-create-1.jpg
--------------------------------------------------------------------------------
/server/src/notification/notification-type.ts:
--------------------------------------------------------------------------------
1 | export enum NotificationType {
2 | InsufficientBalance = 'InsufficientBalance',
3 | }
4 |
--------------------------------------------------------------------------------
/docs/zh/cloud-storage/website-hosting-domain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/cloud-storage/website-hosting-domain.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/MediaPlatformBaseSetting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/MediaPlatformBaseSetting.png
--------------------------------------------------------------------------------
/docs/zh/doc-images/MediaPlatformBaseSetting2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/docs/zh/doc-images/MediaPlatformBaseSetting2.png
--------------------------------------------------------------------------------
/packages/client-sdk/src/request/index.ts:
--------------------------------------------------------------------------------
1 | export * from './request'
2 | export * from './request-uni'
3 | export * from './request-wxmp'
4 |
--------------------------------------------------------------------------------
/packages/database-proxy/src/accessor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './accessor'
2 |
3 | export * from './mongo'
4 |
5 | export * from './mysql'
6 |
--------------------------------------------------------------------------------
/packages/node-modules-utils/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './package'
2 | export * from './declaration'
3 | export * from './import-parser'
4 |
--------------------------------------------------------------------------------
/packages/run-tests.sh:
--------------------------------------------------------------------------------
1 | docker run --rm -p 27018:27017 --name mongotest -d mongo
2 | npx mocha ./*/tests/**/*.test.js
3 | docker rm -f mongotest
--------------------------------------------------------------------------------
/server/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/web/src/components/DateRangePicker/index.css:
--------------------------------------------------------------------------------
1 | .rdp-day_selected {
2 | background-color: #00a9a6 !important;
3 | color: white !important;
4 | }
5 |
--------------------------------------------------------------------------------
/runtimes/nodejs/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 |
4 | upload
5 | data/*
6 | tmp
7 |
8 | .env
9 |
10 | ecosystem.config.js
11 | .DS_Store
12 |
--------------------------------------------------------------------------------
/cli/src/util/print.ts:
--------------------------------------------------------------------------------
1 | import * as emoji from 'node-emoji'
2 |
3 | export function getEmoji(value: any) {
4 | return emoji.get(emoji.find(value).key)
5 | }
6 |
--------------------------------------------------------------------------------
/server/src/i18n/zh/notification.json:
--------------------------------------------------------------------------------
1 | {
2 | "InsufficientBalance": {
3 | "title": "laf 账户欠费",
4 | "content": "你的账户已欠费,应用 {appid} 将停止运行,请及时充值"
5 | }
6 | }
--------------------------------------------------------------------------------
/server/src/storage/minio/types.ts:
--------------------------------------------------------------------------------
1 | export type MinioCommandExecOutput = {
2 | status: 'success' | 'error'
3 | error?: any
4 | [key: string]: any
5 | }
6 |
--------------------------------------------------------------------------------
/cli/template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "laf-app",
3 | "description": "the app engine service of lat",
4 | "dependencies": {},
5 | "devDependencies": {}
6 | }
--------------------------------------------------------------------------------
/server/src/i18n/zh-CN/notification.json:
--------------------------------------------------------------------------------
1 | {
2 | "InsufficientBalance": {
3 | "title": "laf 账户欠费",
4 | "content": "你的账户已欠费,应用 {appid} 将停止运行,请及时充值"
5 | }
6 | }
--------------------------------------------------------------------------------
/docs/zh/cloud-function/cron.md:
--------------------------------------------------------------------------------
1 |
2 | # 定时任务
3 |
4 | 本节介绍使用触发器,定时触发云函数的执行。
5 |
6 | 
7 |
8 | 如图,在「应用开发控制台」中,云函数编辑器页面左上触,可打开触发器管理面板,按界面操作即可新建定时触发器来实现定时任务。
--------------------------------------------------------------------------------
/runtimes/nodejs/src/support/engine/index.ts:
--------------------------------------------------------------------------------
1 | export * from './cache'
2 |
3 | export * from './executor'
4 |
5 | export * from './types'
6 |
7 | export * from './console'
8 |
--------------------------------------------------------------------------------
/web/src/components/EditableTable/index.module.scss:
--------------------------------------------------------------------------------
1 | .text {
2 | white-space: nowrap;
3 | overflow: hidden;
4 | text-overflow: ellipsis;
5 | font-family: Inter;
6 | }
7 |
--------------------------------------------------------------------------------
/web/src/pages/app/setting/index.css:
--------------------------------------------------------------------------------
1 | /* stylelint-disable selector-class-pattern */
2 | .chakra-modal__content-container::-webkit-scrollbar {
3 | width: 0;
4 | height: 0;
5 | }
--------------------------------------------------------------------------------
/server/src/database/entities/database-sync-record.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export class DatabaseSyncRecord {
4 | uid: ObjectId
5 | createdAt: Date
6 | }
7 |
--------------------------------------------------------------------------------
/web/src/utils/getAvatarUrl.ts:
--------------------------------------------------------------------------------
1 | export function getAvatarUrl(uid?: string, updatedAt?: string) {
2 | return `${window.location.origin}/v1/user/avatar/${uid}?t=${updatedAt}`;
3 | }
4 |
--------------------------------------------------------------------------------
/server/src/group/group-role.decorator.ts:
--------------------------------------------------------------------------------
1 | import { SetMetadata } from '@nestjs/common'
2 |
3 | export const GroupRoles = (...roles: string[]) =>
4 | SetMetadata('group-roles', roles)
5 |
--------------------------------------------------------------------------------
/web/src/pages/app/functions/mods/FunctionPanel/index.css:
--------------------------------------------------------------------------------
1 | .funcList .simplebar-scrollbar::before {
2 | background: #dee0e2;
3 | width: 4px;
4 | transform: translateX(100%);
5 | }
6 |
--------------------------------------------------------------------------------
/web/src/pages/app/functions/mods/HeadPanel/index.css:
--------------------------------------------------------------------------------
1 | .recentList .simplebar-scrollbar::before {
2 | background: #dee0e2;
3 | height: 6px;
4 | transform: translateY(50%);
5 | }
6 |
--------------------------------------------------------------------------------
/web/src/pages/app/storages/mods/index.module.scss:
--------------------------------------------------------------------------------
1 | .circle::before {
2 | display: inline-block;
3 | width: 8px;
4 | height: 8px;
5 | border-radius: 50%;
6 | margin-right: 4px;
7 | }
8 |
--------------------------------------------------------------------------------
/runtimes/nodejs/src/support/types.ts:
--------------------------------------------------------------------------------
1 | import { Request } from 'express'
2 |
3 | export interface IRequest extends Request {
4 | user?: any
5 | requestId?: string
6 | [key: string]: any
7 | }
8 |
--------------------------------------------------------------------------------
/web/src/pages/app/database/CollectionDataList/mods/DataPanel/index.module.scss:
--------------------------------------------------------------------------------
1 | .simplebar-scrollbar::before {
2 | background: #7b838b;
3 | width: 4px;
4 | transform: translateX(100%);
5 | }
6 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [!{node_modules}/**]
4 | end_of_line = lf
5 | charset = utf-8
6 | insert_final_newline = true
7 |
8 | [{*.js,*.ts}]
9 | indent_style = space
10 | indent_size = 2
--------------------------------------------------------------------------------
/web/public/js/monaco-editor.0.43.0/base/browser/ui/codicons/codicon/codicon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/labring/laf/HEAD/web/public/js/monaco-editor.0.43.0/base/browser/ui/codicons/codicon/codicon.ttf
--------------------------------------------------------------------------------
/server/src/user/dto/update-avatar.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 |
3 | export class UpdateAvatarDto {
4 | @ApiProperty({ type: 'string', format: 'binary' })
5 | avatar: any
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/recycle-bin/entities/recycle-bin.ts:
--------------------------------------------------------------------------------
1 | export enum DataType {
2 | FUNCTION = 'function',
3 | }
4 |
5 | export class RecycleBin {
6 | type: DataType
7 | data: any
8 | createdAt: Date
9 | }
10 |
--------------------------------------------------------------------------------
/docs/zh/examples/index.md:
--------------------------------------------------------------------------------
1 |
2 | # laf 使用实例
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | ## 云存储
11 | - [微信小程序上传文件](/zh/examples/wxmp-upload.md)
12 | - [用 GitHub Action 自动构建前端并发布到网站托管](/zh/examples/website-hosting-ci-cd.md)
--------------------------------------------------------------------------------
/packages/database-proxy/docs/todo.md:
--------------------------------------------------------------------------------
1 |
2 | ### 规则相关
3 |
4 | #### 1. 将规则测试用例拆到单独的测试文件中,不断完善每种规则的测试覆盖
5 |
6 | #### 2. query 规则为数组时,缺少相关测试用例,此功能尚未验证可用性
7 |
8 | ### 代码优化
9 |
10 | #### 1. 给 ruler 和 validator 代码添加丰富的注释
--------------------------------------------------------------------------------
/server/src/authentication/jwt.auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common'
2 | import { AuthGuard } from '@nestjs/passport'
3 |
4 | @Injectable()
5 | export class JwtAuthGuard extends AuthGuard('jwt') {}
6 |
--------------------------------------------------------------------------------
/packages/client-sdk/tests/http/config.js:
--------------------------------------------------------------------------------
1 | const config = {
2 | dbProxyUrl:
3 | 'https://6217ba84-5f56-45b1-a46b-7fb69a7ea1e9.lafyun.com/proxy/app',
4 | getAccessToken: () => '',
5 | }
6 |
7 | module.exports = config
8 |
--------------------------------------------------------------------------------
/server/src/database/dto/update-dedicated-database.dto.ts:
--------------------------------------------------------------------------------
1 | import { CreateDedicatedDatabaseDto } from './create-dedicated-database.dto'
2 |
3 | export class UpdateDedicatedDatabaseDto extends CreateDedicatedDatabaseDto {}
4 |
--------------------------------------------------------------------------------
/server/src/billing/interface/billing-query.interface.ts:
--------------------------------------------------------------------------------
1 | export interface BillingQuery {
2 | appid?: string[]
3 | startTime?: Date
4 | endTime?: Date
5 | page?: number
6 | pageSize?: number
7 | state?: string
8 | }
9 |
--------------------------------------------------------------------------------
/packages/database-ql/src/geo/index.ts:
--------------------------------------------------------------------------------
1 | export * from './point'
2 | export * from './lineString'
3 | export * from './polygon'
4 | export * from './multiPoint'
5 | export * from './multiLineString'
6 | export * from './multiPolygon'
7 |
--------------------------------------------------------------------------------
/server/src/trigger/dto/update-trigger.dto.ts:
--------------------------------------------------------------------------------
1 | import { PartialType } from '@nestjs/swagger'
2 | import { CreateTriggerDto } from './create-trigger.dto'
3 |
4 | export class UpdateTriggerDto extends PartialType(CreateTriggerDto) {}
5 |
--------------------------------------------------------------------------------
/packages/database-proxy/tests/units/policy/rules.json:
--------------------------------------------------------------------------------
1 | {
2 | "categories": {
3 | "read": true,
4 | "update": true,
5 | "$schema": {
6 | "account": { "match": "^\\d{6,10}$" }
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('ts-jest').JestConfigWithTsJest} */
2 | module.exports = {
3 | preset: 'ts-jest',
4 | testEnvironment: 'node',
5 | testSequencer: './jest-sequencer.js',
6 | maxWorkers: 1,
7 | verbose: true,
8 | }
9 |
--------------------------------------------------------------------------------
/server/src/storage/entities/minio.ts:
--------------------------------------------------------------------------------
1 | export class MinioUser {
2 | accessKey: string
3 | policyName: string
4 | userStatus: 'enabled' | 'disabled'
5 | memberOf: {
6 | name: string
7 | policies: string[]
8 | }[]
9 | }
10 |
--------------------------------------------------------------------------------
/web/src/pages/app/database/mods/AddRulesModal/policyTemplate.ts:
--------------------------------------------------------------------------------
1 | const policyTemplate = {
2 | read: true,
3 | count: true,
4 | update: false,
5 | remove: false,
6 | add: false,
7 | };
8 |
9 | export default policyTemplate;
10 |
--------------------------------------------------------------------------------
/server/build-image.sh:
--------------------------------------------------------------------------------
1 | # Warning: just for development phase, will be move to github action in future.
2 |
3 |
4 |
5 | docker buildx build --platform linux/amd64,linux/arm64 --push -t docker.io/lafyun/laf-server:debug-202306151521 -f Dockerfile .
6 |
--------------------------------------------------------------------------------
/server/src/i18n/en/notification.json:
--------------------------------------------------------------------------------
1 | {
2 | "InsufficientBalance": {
3 | "title": "Laf account is in arrears",
4 | "content": "Your account is in arrears, the app {appid} will stop running, please recharge your account promptly!"
5 | }
6 | }
--------------------------------------------------------------------------------
/packages/cloud-sdk/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Cloud } from './cloud'
2 |
3 | export * from './cloud.interface'
4 | export * from './function.interface'
5 | export * from './cloud'
6 |
7 | const cloud = new Cloud()
8 |
9 | export default cloud
10 |
--------------------------------------------------------------------------------
/server/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/web/src/components/Content/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | export default function Content(props: { children: React.ReactNode }) {
4 | return
{props.children}
;
5 | }
6 |
--------------------------------------------------------------------------------
/cli/src/action/policy/dto.ts:
--------------------------------------------------------------------------------
1 | interface PolicyRule {
2 | collectionName: string
3 | rules: Rules
4 | }
5 |
6 | interface Rules {
7 | read: boolean
8 | count: boolean
9 | update: boolean
10 | remove: boolean
11 | add: boolean
12 | }
13 |
--------------------------------------------------------------------------------
/packages/database-proxy/tests/mongo_db/_db.js:
--------------------------------------------------------------------------------
1 | const dbconfig = {
2 | dbName: 'testdb',
3 | url: 'mongodb://localhost:27018',
4 | connSettings: {
5 | directConnection: true,
6 | },
7 | }
8 |
9 | module.exports = {
10 | dbconfig,
11 | }
12 |
--------------------------------------------------------------------------------
/server/src/initializer/deploy-manifest/databaseOpsRequestStart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps.kubeblocks.io/v1alpha1
2 | kind: OpsRequest
3 | metadata:
4 | name: <%- name %>
5 | namespace: laf-system
6 | spec:
7 | clusterRef: <%- clusterName %>
8 | type: Start
9 |
--------------------------------------------------------------------------------
/server/src/initializer/deploy-manifest/databaseOpsRequestStop.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps.kubeblocks.io/v1alpha1
2 | kind: OpsRequest
3 | metadata:
4 | name: <%- name %>
5 | namespace: laf-system
6 | spec:
7 | clusterRef: <%- clusterName %>
8 | type: Stop
9 |
--------------------------------------------------------------------------------
/web/src/layouts/Auth/index.module.scss:
--------------------------------------------------------------------------------
1 | .container {
2 | height: 100vh;
3 | width: 100vw;
4 | background-image: url("@/assets/login_bg.svg");
5 | background-repeat: no-repeat;
6 | background-position: left bottom;
7 | background-size: 56%;
8 | }
9 |
--------------------------------------------------------------------------------
/server/src/billing/dto/billings.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 |
3 | export class BillingsByDayDto {
4 | @ApiProperty({ type: String })
5 | totalAmount: number
6 |
7 | @ApiProperty({ type: Date })
8 | day: Date
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/function-template/dto/function-template-usedBy.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class GetFunctionTemplateUsedByDto {
5 | @ApiProperty({ type: String })
6 | uid: ObjectId
7 | }
8 |
--------------------------------------------------------------------------------
/cli/src/common/prompts.ts:
--------------------------------------------------------------------------------
1 | import * as prompts from 'prompts'
2 |
3 | export async function confirm(message: string) {
4 | return await prompts({
5 | type: 'confirm',
6 | name: 'value',
7 | message: message,
8 | initial: false,
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/runtimes/nodejs/.dockerignore:
--------------------------------------------------------------------------------
1 | # node_modules
2 | .env
3 | ecosystem.config.js
4 | # dist
5 | data
6 | # src
7 | tests
8 | commitlint.config.js
9 | ecosystem.config.js.tpl
10 | .DS_Store
11 | .env.development
12 | .env.production
13 | .gitignore
14 | Dockerfile
15 | http
--------------------------------------------------------------------------------
/server/src/database/dto/update-policy.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString } from 'class-validator'
3 | export class UpdatePolicyDto {
4 | @ApiProperty()
5 | @IsNotEmpty()
6 | @IsString()
7 | injector: string
8 | }
9 |
--------------------------------------------------------------------------------
/server/src/recycle-bin/cloud-function/interface/function-recycle-bin-query.interface.ts:
--------------------------------------------------------------------------------
1 | export interface CloudFunctionRecycleBinQuery {
2 | name?: string
3 | appid?: string
4 | startTime?: Date
5 | endTime?: Date
6 | page?: number
7 | pageSize?: number
8 | }
9 |
--------------------------------------------------------------------------------
/runtimes/nodejs/Dockerfile.init:
--------------------------------------------------------------------------------
1 | FROM node:20.10.0
2 |
3 | WORKDIR /app
4 |
5 | COPY ./init.sh /app/init.sh
6 | COPY ./upload-dependencies.sh /app/upload-dependencies.sh
7 |
8 | RUN chown -R node:node /app
9 |
10 | USER node
11 |
12 | CMD [ "sh", "/app/init.sh" ]
13 |
--------------------------------------------------------------------------------
/server/src/utils/crypto.ts:
--------------------------------------------------------------------------------
1 | import * as crypto from 'crypto'
2 |
3 | // use sha256 to hash the password
4 | export function hashPassword(password: string): string {
5 | const hash = crypto.createHash('sha256')
6 | hash.update(password)
7 | return hash.digest('hex')
8 | }
9 |
--------------------------------------------------------------------------------
/web/src/components/Markdown/formatLinkText.ts:
--------------------------------------------------------------------------------
1 | export const formatLinkText = (text: string) => {
2 | const httpReg =
3 | /(http|https|ftp):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/gi;
4 | return text.replace(httpReg, ` $& `);
5 | };
6 |
--------------------------------------------------------------------------------
/server/src/database/dto/create-policy.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class CreatePolicyDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @IsString()
8 | name: string
9 | }
10 |
--------------------------------------------------------------------------------
/web/public/homepage/Vector.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/web/src/utils/getRegionById.ts:
--------------------------------------------------------------------------------
1 | import { TRegion } from "@/apis/typing";
2 |
3 | function getRegionById(regions: TRegion[] | undefined, id: string): TRegion | undefined {
4 | return (regions || []).find((region) => region._id === id);
5 | }
6 |
7 | export default getRegionById;
8 |
--------------------------------------------------------------------------------
/packages/node-modules-utils/copy2app.sh:
--------------------------------------------------------------------------------
1 | rm -rf ../app-service/node_modules/node-modules-utils/dist
2 | rm -rf ../app-service/node_modules/node-modules-utils/src
3 | cp -r dist ../app-service/node_modules/node-modules-utils/dist
4 | cp -r src ../app-service/node_modules/node-modules-utils/src
--------------------------------------------------------------------------------
/server/src/authentication/dto/github-signin.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class GithubSigninDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @IsString()
8 | code: string
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/website/dto/update-website.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class BindCustomDomainDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @IsString()
8 | domain: string
9 | }
10 |
--------------------------------------------------------------------------------
/cli/src/api/pat.ts:
--------------------------------------------------------------------------------
1 | import { request } from '../util/request'
2 |
3 | export async function pat2token(server: string, data: { pat: string }): Promise {
4 | return request({
5 | url: server + `/v1/auth/pat2token`,
6 | method: 'POST',
7 | data: data,
8 | })
9 | }
10 |
--------------------------------------------------------------------------------
/packages/database-proxy/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './proxy'
2 | export * from './policy'
3 | export * from './accessor'
4 | export * from './types'
5 | export * from './processor'
6 |
7 | export * from './dbi'
8 | export * from './logger'
9 |
10 | export { Db } from 'database-ql'
11 |
--------------------------------------------------------------------------------
/server/src/dependency/dto/delete-dependency.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, Length } from 'class-validator'
3 |
4 | export class DeleteDependencyDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @Length(1, 64)
8 | name: string
9 | }
10 |
--------------------------------------------------------------------------------
/cli/src/command/deploy/index.ts:
--------------------------------------------------------------------------------
1 | import { Command, program } from 'commander'
2 | import { deploy } from '../../action/deploy'
3 |
4 | export function command(): Command {
5 | const cmd = program.command('deploy').action(() => {
6 | deploy()
7 | })
8 |
9 | return cmd
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/authentication/dto/github-jump-login.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class GithubJumpLoginDto {
5 | @ApiProperty()
6 | @IsString()
7 | @IsNotEmpty()
8 | redirectUri: string
9 | }
10 |
--------------------------------------------------------------------------------
/packages/eslint-config-laf/runtime.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: './package.js',
3 | rules: {
4 | 'prettier/prettier': [
5 | 'error',
6 | {
7 | singleQuote: true,
8 | trailingComma: 'all',
9 | semi: false,
10 | },
11 | ],
12 | },
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/group/dto/create-group.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString, Length } from 'class-validator'
3 |
4 | export class CreateGroupDto {
5 | @ApiProperty()
6 | @IsString()
7 | @IsNotEmpty()
8 | @Length(1, 64)
9 | name: string
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/group/dto/update-group.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString, Length } from 'class-validator'
3 |
4 | export class UpdateGroupDto {
5 | @ApiProperty()
6 | @IsString()
7 | @IsNotEmpty()
8 | @Length(1, 64)
9 | name: string
10 | }
11 |
--------------------------------------------------------------------------------
/web/src/pages/homepage/video.tsx:
--------------------------------------------------------------------------------
1 | import { site_url } from "@/constants";
2 |
3 | export default function Video() {
4 | return (
5 | <>
6 |
9 | >
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/cli/src/util/sys.ts:
--------------------------------------------------------------------------------
1 | import { ProjectSchema } from '../schema/project'
2 |
3 | export function getAppPath(): string {
4 | return process.cwd()
5 | }
6 |
7 | export function getBaseDir(): string {
8 | const projectSchema = ProjectSchema.read()
9 | return projectSchema?.spec?.baseDir || './'
10 | }
11 |
--------------------------------------------------------------------------------
/packages/node-modules-utils/README.md:
--------------------------------------------------------------------------------
1 | # `node-modules-utils`
2 |
3 | > 用于加载、解析项目本地 node_modules 中依赖的信息, 用于 `less-framework` 中, 主要用来获取包的 Typescript 类型文件,供 Web IDE 在线类型提示和补全使用。
4 |
5 | ## Usage
6 |
7 | ```
8 | const nmUtils = require('node-modules-utils');
9 |
10 | // TODO: DEMONSTRATE API
11 | ```
12 |
--------------------------------------------------------------------------------
/server/src/account/interface/account-query.interface.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export interface AccountChargeOrderQuery {
4 | phase?: string
5 | id?: ObjectId
6 | startTime?: Date
7 | endTime?: Date
8 | page?: number
9 | pageSize?: number
10 | channel?: string
11 | }
12 |
--------------------------------------------------------------------------------
/packages/database-proxy/src/dbi/index.ts:
--------------------------------------------------------------------------------
1 | import { AccessorInterface } from '../accessor'
2 | import { Db } from 'database-ql'
3 | import { Request } from './request'
4 |
5 | export function getDb(accessor: AccessorInterface): Db {
6 | return new Db({
7 | request: new Request(accessor),
8 | })
9 | }
10 |
--------------------------------------------------------------------------------
/runtimes/nodejs/functions/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "noUnusedLocals": false,
5 | "noUnusedParameters": false,
6 | "baseUrl": "./",
7 | "paths": {
8 | "@/*": ["./*"]
9 | }
10 | },
11 | "include": [
12 | "./*"
13 | ]
14 | }
--------------------------------------------------------------------------------
/server/src/database/dto/update-rule.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsJSON, IsNotEmpty, MaxLength } from 'class-validator'
3 |
4 | export class UpdatePolicyRuleDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @MaxLength(2048)
8 | @IsJSON()
9 | value: string
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/database/dto/import-database.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 |
3 | export class ImportDatabaseDto {
4 | @ApiProperty({ type: 'binary', format: 'binary' })
5 | file: any
6 |
7 | @ApiProperty({ type: 'string', description: 'source appid' })
8 | sourceAppid: string
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/function/dto/update-function-debug.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsObject } from 'class-validator'
3 |
4 | export class UpdateFunctionDebugDto {
5 | @ApiProperty()
6 | @IsObject()
7 | params: any
8 |
9 | validate() {
10 | return null
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/initializer/deploy-manifest/databaseOpsRequestRestart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps.kubeblocks.io/v1alpha1
2 | kind: OpsRequest
3 | metadata:
4 | name: <%- name %>
5 | namespace: laf-system
6 | spec:
7 | clusterRef: <%- clusterName %>
8 | type: Restart
9 | restart:
10 | - componentName: mongodb
11 |
--------------------------------------------------------------------------------
/web/src/components/IconText/index.module.scss:
--------------------------------------------------------------------------------
1 | .iconText {
2 | color: #7b838b;
3 |
4 | svg {
5 | fill: #7b838b !important;
6 | }
7 |
8 | &:hover {
9 | color: var(--chakra-colors-grayModern-600);
10 | svg {
11 | fill: var(--chakra-colors-grayModern-600) !important;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/server/src/setting/setting.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { SettingService } from './setting.service'
3 | import { SettingController } from './setting.controller'
4 |
5 | @Module({
6 | providers: [SettingService],
7 | controllers: [SettingController],
8 | })
9 | export class SettingModule {}
10 |
--------------------------------------------------------------------------------
/web/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "composite": true,
5 | "module": "ESNext",
6 | "skipLibCheck": true,
7 | "moduleResolution": "Node",
8 | "allowSyntheticDefaultImports": true,
9 | "types": ["node"]
10 | },
11 | "include": ["vite.config.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/runtimes/nodejs/src/support/logger.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @Author: Maslow
3 | * @Date: 2021-07-30 10:30:29
4 | * @LastEditTime: 2021-10-06 19:26:58
5 | * @Description:
6 | */
7 |
8 | import { Console } from './engine'
9 |
10 | /**
11 | * The global logger instance
12 | */
13 | export const logger = new Console('#')
14 |
--------------------------------------------------------------------------------
/server/src/account/entities/account-gift-code.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export class GiftCode {
4 | _id?: ObjectId
5 | code: string
6 | creditAmount: number
7 | used: boolean
8 | usedBy?: ObjectId
9 | usedAt?: Date
10 | createdAt: Date
11 | expiredAt?: Date
12 | transactionId?: ObjectId
13 | }
14 |
--------------------------------------------------------------------------------
/docs/scripts/check-version.js:
--------------------------------------------------------------------------------
1 | // Lock lockFileVersion to version 2 And resolve import error when import xxx from 'node:xxx'
2 | if (process.version && +process.version.slice(1).split('.')[0] < 18) {
3 | console.log(
4 | `Required node version >= 18 not satisfied with current version ${process.version}.`
5 | )
6 | process.exit(1)
7 | }
8 |
--------------------------------------------------------------------------------
/server/src/account/dto/use-gift-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, Length } from 'class-validator'
3 |
4 | export class UseGiftCodeDto {
5 | @ApiProperty({
6 | description: 'gift code',
7 | type: 'string',
8 | })
9 | @IsNotEmpty()
10 | @Length(8, 64)
11 | code: string
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/database/dto/create-collection.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, Length } from 'class-validator'
3 |
4 | export class CreateCollectionDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @Length(3, 32)
8 | name: string
9 |
10 | async validate() {
11 | return null
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/group/dto/update-group-member-role.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsEnum } from 'class-validator'
2 | import { GroupRole } from '../entities/group-member'
3 | import { ApiProperty } from '@nestjs/swagger'
4 |
5 | export class UpdateGroupMemberRoleDto {
6 | @ApiProperty({ enum: GroupRole })
7 | @IsEnum(GroupRole)
8 | role: GroupRole
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/storage/dto/update-bucket.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsEnum } from 'class-validator'
3 | import { BucketPolicy } from '../entities/storage-bucket'
4 |
5 | export class UpdateBucketDto {
6 | @ApiProperty({ enum: BucketPolicy })
7 | @IsEnum(BucketPolicy)
8 | policy: BucketPolicy
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/user/entities/user-avatar.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class UserAvatar {
5 | @ApiProperty({ type: Buffer })
6 | data: Buffer
7 |
8 | @ApiProperty({ type: String })
9 | createdBy: ObjectId
10 |
11 | @ApiProperty()
12 | createdAt: Date
13 | }
14 |
--------------------------------------------------------------------------------
/web/.env:
--------------------------------------------------------------------------------
1 | # keep it default "" in both dev or prod environment unless you must use a custom server api
2 | VITE_SERVER_BASE_URL=
3 |
4 | # this only used for dev environment, change it to your local api server url if needed
5 | # don't change it directly, you should create a .env.local file and set it there
6 | VITE_DEV_SERVER_URL=http://api.laf.run
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Join Our Discord
4 | url: https://discord.gg/uWZqAwwdvy
5 | about: Join our community, we will keep you in the loop.
6 | - name: Contact US / Business Inquiries
7 | url: https://docs.qq.com/form/page/DS0tCWXpQc2NpR3dR
8 | about: Please contact us.
--------------------------------------------------------------------------------
/packages/eslint-config-laf/cli.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: './package.js',
3 | rules: {
4 | 'prettier/prettier': [
5 | 'error',
6 | {
7 | singleQuote: true,
8 | trailingComma: 'all',
9 | semi: false,
10 | printWidth: 120,
11 | tabWidth: 2,
12 | },
13 | ],
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/server/src/function/dto/compile-function.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class CompileFunctionDto {
5 | @ApiProperty({
6 | description: 'The source code of the function',
7 | })
8 | @IsNotEmpty()
9 | @IsString()
10 | code: string
11 | }
12 |
--------------------------------------------------------------------------------
/packages/database-proxy/tests/mysql_db/_db.js:
--------------------------------------------------------------------------------
1 | // docker run --name mysqldb -e MYSQL_ROOT_PASSWORD=kissme -e MYSQL_DATABASE=testdb -d -p 3306:3306 mysql
2 | const dbconfig = {
3 | db: 'testdb',
4 | user: 'root',
5 | password: 'kissme',
6 | host: 'localhost',
7 | port: 3306,
8 | connectionLimit: 30,
9 | }
10 |
11 | module.exports = dbconfig
12 |
--------------------------------------------------------------------------------
/web/.swagger.config.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | swaggerPath: "http://api.maslow-dev.lafyun.com/-json",
4 | typingFileName: "api-auto.d.ts",
5 |
6 | outDir: "src/apis/v1",
7 | request: "import request from '@/utils/request';",
8 | fileNameRule: function (url) {
9 | return url.split("/")[2];
10 | },
11 | },
12 | ];
13 |
--------------------------------------------------------------------------------
/e2e/system-db.ts:
--------------------------------------------------------------------------------
1 | import { Config } from './config'
2 | import { MongoClient } from 'mongodb'
3 |
4 | export async function getDbClient() {
5 | const client = new MongoClient(Config.MONGO_URI)
6 | await client.connect()
7 | return client
8 | }
9 |
10 | export async function getDb() {
11 | const client = await getDbClient()
12 | return client.db()
13 | }
14 |
--------------------------------------------------------------------------------
/packages/cloud-sdk/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | > @lafjs/cloud is used in cloud function, exposing resource objects to cloud function.
5 |
6 | ```ts
7 | import cloud from '@lafjs/cloud'
8 |
9 | exports.main = async function (ctx) {
10 |
11 | const db = cloud.database()
12 | const res = await db.collection('messages').get()
13 |
14 | return res.data
15 | }
16 | ```
--------------------------------------------------------------------------------
/server/src/group/dto/find-group-member.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { OmitType } from '@nestjs/mapped-types'
3 | import { GroupMember } from '../entities/group-member'
4 |
5 | export class FindGroupMemberDto extends OmitType(GroupMember, [
6 | 'groupId',
7 | '_id',
8 | ]) {
9 | @ApiProperty()
10 | username: string
11 | }
12 |
--------------------------------------------------------------------------------
/server/src/user/entities/user-password.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export enum UserPasswordState {
4 | Active = 'Active',
5 | Inactive = 'Inactive',
6 | }
7 |
8 | export class UserPassword {
9 | _id?: ObjectId
10 | uid: ObjectId
11 | password: string
12 | state: UserPasswordState
13 | createdAt: Date
14 | updatedAt: Date
15 | }
16 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "dbaeumer.vscode-eslint",
4 | "christian-kohler.npm-intellisense",
5 | "streetsidesoftware.code-spell-checker",
6 | "pomdtr.excalidraw-editor",
7 | "Tim-Koehler.helm-intellisense",
8 | "lokalise.i18n-ally",
9 | "stylelint.vscode-stylelint",
10 | "EditorConfig.EditorConfig"
11 | ]
12 | }
--------------------------------------------------------------------------------
/server/src/database/dto/update-collection.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiPropertyOptional } from '@nestjs/swagger'
2 | import { IsObject, IsString } from 'class-validator'
3 |
4 | export class UpdateCollectionDto {
5 | @ApiPropertyOptional()
6 | @IsObject()
7 | validatorSchema: object
8 |
9 | @ApiPropertyOptional()
10 | @IsString()
11 | validationLevel: string
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/dependency/dto/create-dependency.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, Length } from 'class-validator'
3 |
4 | export class CreateDependencyDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @Length(1, 64)
8 | name: string
9 |
10 | @ApiProperty()
11 | @IsNotEmpty()
12 | @Length(1, 64)
13 | spec: string
14 | }
15 |
--------------------------------------------------------------------------------
/server/src/dependency/dto/update-dependency.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, Length } from 'class-validator'
3 |
4 | export class UpdateDependencyDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @Length(1, 64)
8 | name: string
9 |
10 | @ApiProperty()
11 | @IsNotEmpty()
12 | @Length(1, 64)
13 | spec: string
14 | }
15 |
--------------------------------------------------------------------------------
/server/src/user/dto/bind-username.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString, Length } from 'class-validator'
3 |
4 | export class BindUsernameDto {
5 | @ApiProperty({
6 | description: 'username',
7 | example: 'laf-user',
8 | })
9 | @IsString()
10 | @IsNotEmpty()
11 | @Length(3, 64)
12 | username: string
13 | }
14 |
--------------------------------------------------------------------------------
/web/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | *.log
3 | npm-debug.log*
4 | yarn-debug.log*
5 | yarn-error.log*
6 | pnpm-debug.log*
7 | lerna-debug.log*
8 |
9 | node_modules
10 | dist
11 | dist-ssr
12 | dev-dist
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/server/src/interceptor/interceptor.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { HttpInterceptorService } from './http-interceptor.service'
3 | import { HttpModule } from '@nestjs/axios'
4 |
5 | @Module({
6 | imports: [HttpModule],
7 | providers: [HttpInterceptorService],
8 | exports: [HttpInterceptorService],
9 | })
10 | export class InterceptorModule {}
11 |
--------------------------------------------------------------------------------
/packages/client-sdk/src/index-bundle.ts:
--------------------------------------------------------------------------------
1 | import { init, Cloud, Db, EnvironmentType } from './index'
2 |
3 | export * from './index'
4 |
5 | // 此行是为了运行测试用例时, 报 window undefined 使用;
6 | // 如果浏览器环境因此报错, 需要注释掉本行;
7 | // var window: any
8 |
9 | if (window) {
10 | window['LafClient'] = {
11 | initLessClient: init,
12 | Cloud,
13 | Db,
14 | EnvironmentType,
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/web/src/components/DependenceList/index.module.scss:
--------------------------------------------------------------------------------
1 | .dependenceList {
2 | max-height: 60vh;
3 | overflow: auto;
4 |
5 | li {
6 | cursor: pointer;
7 | display: flex;
8 | min-height: 80px;
9 | align-items: center;
10 | justify-content: space-between;
11 | padding: 5px 8px;
12 |
13 | span {
14 | vertical-align: middle;
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/web/src/pages/homepage/status.module.scss:
--------------------------------------------------------------------------------
1 | .breathing-gradient {
2 | background: #5cdd8b;
3 | display: inline-block;
4 | border-radius: 50rem;
5 | width: 5px;
6 | height: 16px;
7 | margin-right: 2px;
8 | }
9 |
10 | @keyframes breathing {
11 | 0% {
12 | opacity: 0.6;
13 | }
14 | 50% {
15 | opacity: 1;
16 | }
17 | 100% {
18 | opacity: 0.6;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/web/src/utils/getPageInfo.ts:
--------------------------------------------------------------------------------
1 | import { PageValues } from "@/components/Pagination";
2 |
3 | export default function getPageInfo(data: {
4 | pageSize: number;
5 | page: number;
6 | total: number;
7 | [key: string]: any;
8 | }): PageValues {
9 | return {
10 | pageSize: data?.pageSize,
11 | limit: data?.pageSize,
12 | page: data?.page,
13 | total: data?.total,
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/server/src/group/entities/group-application.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class GroupApplication {
5 | @ApiProperty({ type: 'string' })
6 | _id?: ObjectId
7 |
8 | @ApiProperty({ type: 'string' })
9 | groupId: ObjectId
10 |
11 | @ApiProperty()
12 | appid: string
13 |
14 | @ApiProperty()
15 | createdAt: Date
16 | }
17 |
--------------------------------------------------------------------------------
/server/src/initializer/initializer.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { RegionService } from 'src/region/region.service'
3 | import { MinioService } from 'src/storage/minio/minio.service'
4 | import { InitializerService } from './initializer.service'
5 |
6 | @Module({
7 | providers: [InitializerService, MinioService, RegionService],
8 | })
9 | export class InitializerModule {}
10 |
--------------------------------------------------------------------------------
/.lycheeignore:
--------------------------------------------------------------------------------
1 | .*appid.*
2 | .*xx.*
3 | https://beian.miit.gov.cn/
4 | .*127-0-0-1.*
5 | https://oss.laf.run
6 | https://github.com/labring/laf/edit/main/docs/
7 | https://openapi.alipaydev.com/gateway.do
8 | https://github.com/labring/laf/commit/
9 | https://github.com/labring/laf/issues/
10 | https://twitter.com/laf_dev
11 | https://oss.laf.dev
12 | https://oss.laf.dev/
13 | https://laf.run/v1/auth/passwd/signin
--------------------------------------------------------------------------------
/docs/.vitepress/theme/custom.css:
--------------------------------------------------------------------------------
1 | .VPSidebar::-webkit-scrollbar {
2 | display: none;
3 | }
4 |
5 | /*
6 | .VPDocAside .outline-link {
7 | color: rgb(6, 63, 148);
8 | }
9 |
10 | .VPDocAside .outline-link {
11 | font-size: 14px;
12 | }
13 |
14 | .VPDocAside .outline-link.active {
15 | color: rgb(82, 7, 234);
16 | }
17 |
18 |
19 | .VPDocAside .outline-link:hover {
20 | color: rgb(82, 7, 234);
21 | } */
--------------------------------------------------------------------------------
/server/src/authentication/dto/pat2token.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class Pat2TokenDto {
5 | @ApiProperty({
6 | description: 'PAT',
7 | example:
8 | 'laf_1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
9 | })
10 | @IsString()
11 | @IsNotEmpty()
12 | pat: string
13 | }
14 |
--------------------------------------------------------------------------------
/web/src/components/Editor/index.scss:
--------------------------------------------------------------------------------
1 | .code .property {
2 | color: #A31515
3 | }
4 |
5 | .code .number {
6 | color: #01a99d
7 | }
8 |
9 | .code .string {
10 | color: #0451a5
11 | }
12 |
13 | [data-theme="dark"] .code .property {
14 | color: #9BDCFE
15 | }
16 |
17 | [data-theme="dark"] .code .number {
18 | color: #B0CAA4
19 | }
20 |
21 | [data-theme="dark"] .code .string {
22 | color: #CE9178
23 | }
--------------------------------------------------------------------------------
/server/src/database/dto/create-rule.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsJSON, IsNotEmpty, IsString, MaxLength } from 'class-validator'
3 |
4 | export class CreatePolicyRuleDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @IsString()
8 | collectionName: string
9 |
10 | @ApiProperty()
11 | @IsNotEmpty()
12 | @MaxLength(2048)
13 | @IsJSON()
14 | value: string
15 | }
16 |
--------------------------------------------------------------------------------
/server/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src",
5 | "compilerOptions": {
6 | "assets": [
7 | {
8 | "include": "i18n/**/*",
9 | "watchAssets": true
10 | },
11 | {
12 | "include": "initializer/deploy-manifest/*",
13 | "watchAssets": true
14 | }
15 | ]
16 | }
17 | }
--------------------------------------------------------------------------------
/server/src/i18n/zh/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "create": {
3 | "nameExist": "函数 {name} 已存在",
4 | "maxCount": "达到函数最大数量 {max}",
5 | "error": "创建函数失败"
6 | },
7 | "get": {},
8 | "update": {
9 | "error": "更新函数失败"
10 | },
11 | "delete": {
12 | "error": "删除函数失败"
13 | },
14 | "compile": {
15 | "codeRequired": "函数代码不能为空"
16 | },
17 | "common": {
18 | "notFound": "函数 {name} 不存在"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/server/src/authentication/dto/passwd-check.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString, Length } from 'class-validator'
3 |
4 | export class PasswdCheckDto {
5 | @ApiProperty({
6 | description: 'username | phone | email',
7 | example: 'laf-user | 13805718888 | laf-user@laf.com',
8 | })
9 | @IsString()
10 | @IsNotEmpty()
11 | @Length(3, 64)
12 | username: string
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/group/dto/find-group-invite-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { User } from 'src/user/entities/user'
3 | import { GroupInviteCode } from '../entities/group-invite-code'
4 | import { OmitType } from '@nestjs/mapped-types'
5 |
6 | export class FindGroupInviteCodeDto extends OmitType(GroupInviteCode, [
7 | 'usedBy',
8 | ]) {
9 | @ApiProperty({ type: User })
10 | usedBy: User
11 | }
12 |
--------------------------------------------------------------------------------
/server/src/i18n/zh-CN/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "create": {
3 | "nameExist": "函数 {name} 已存在",
4 | "maxCount": "达到函数最大数量 {max}",
5 | "error": "创建函数失败"
6 | },
7 | "get": {},
8 | "update": {
9 | "error": "更新函数失败"
10 | },
11 | "delete": {
12 | "error": "删除函数失败"
13 | },
14 | "compile": {
15 | "codeRequired": "函数代码不能为空"
16 | },
17 | "common": {
18 | "notFound": "函数 {name} 不存在"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/server/src/authentication/entities/auth-provider.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export enum AuthProviderState {
4 | Enabled = 'Enabled',
5 | Disabled = 'Disabled',
6 | }
7 |
8 | export class AuthProvider {
9 | _id?: ObjectId
10 | name: string
11 | bind: any
12 | register: boolean
13 | default: boolean
14 | state: AuthProviderState
15 | config: any
16 | createdAt: Date
17 | updatedAt: Date
18 | }
19 |
--------------------------------------------------------------------------------
/server/src/recycle-bin/cloud-function/dto/delete-recycle-bin-functions.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsArray, IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class DeleteRecycleBinItemsDto {
5 | @ApiProperty({
6 | description: 'The list of item ids',
7 | type: [String],
8 | })
9 | @IsNotEmpty()
10 | @IsArray()
11 | @IsString({ each: true })
12 | ids: string[]
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/user/dto/bind-email.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsEmail, IsNotEmpty, Length } from 'class-validator'
3 |
4 | export class BindEmailDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @IsEmail()
8 | email: string
9 |
10 | @ApiProperty({
11 | description: 'verify code',
12 | example: '032476',
13 | })
14 | @IsNotEmpty()
15 | @Length(6, 6)
16 | code: string
17 | }
18 |
--------------------------------------------------------------------------------
/server/src/recycle-bin/cloud-function/dto/restore-recycle-bin-functions.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsArray, IsNotEmpty, IsString } from 'class-validator'
3 |
4 | export class RestoreRecycleBinItemsDto {
5 | @ApiProperty({
6 | description: 'The list of item ids',
7 | type: [String],
8 | })
9 | @IsNotEmpty()
10 | @IsArray()
11 | @IsString({ each: true })
12 | ids: string[]
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/utils/interface.ts:
--------------------------------------------------------------------------------
1 | import { Request, Response } from 'express'
2 | import { Application } from 'src/application/entities/application'
3 | import { UserWithProfile } from 'src/user/entities/user'
4 |
5 | export interface IRequest extends Request {
6 | user?: UserWithProfile
7 | application?: Application
8 | [key: string]: any
9 | }
10 |
11 | export interface IResponse extends Response {
12 | [key: string]: any
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/database/dto/update-dedicated-database-state.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsEnum, IsNotEmpty } from 'class-validator'
2 | import { DedicatedDatabaseState } from '../entities/dedicated-database'
3 | import { ApiProperty } from '@nestjs/swagger'
4 |
5 | export class UpdateDedicatedDatabaseStateDto {
6 | @ApiProperty({ enum: DedicatedDatabaseState })
7 | @IsEnum(DedicatedDatabaseState)
8 | @IsNotEmpty()
9 | state: DedicatedDatabaseState
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/group/dto/update-group-invite-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsEnum, IsNotEmpty } from 'class-validator'
3 | import { GroupRole } from '../entities/group-member'
4 | import { ObjectId } from 'mongodb'
5 |
6 | export class GenerateGroupInviteCodeDto {
7 | @ApiProperty({ enum: GroupRole })
8 | @IsEnum(GroupRole)
9 | @IsNotEmpty()
10 | role: GroupRole
11 |
12 | createdBy: ObjectId
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/application/dto/create-env.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString, Length, Matches } from 'class-validator'
3 |
4 | export class CreateEnvironmentDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @IsString()
8 | @Length(1, 64)
9 | @Matches(/^[a-zA-Z_][a-zA-Z0-9_]{1,64}$/)
10 | name: string
11 |
12 | @ApiProperty()
13 | @Length(0, 4096)
14 | @IsString()
15 | value: string
16 | }
17 |
--------------------------------------------------------------------------------
/server/src/trigger/dto/create-trigger.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, Length } from 'class-validator'
3 |
4 | export class CreateTriggerDto {
5 | @ApiProperty()
6 | @IsNotEmpty()
7 | @Length(1, 64)
8 | desc: string
9 |
10 | @ApiProperty()
11 | @IsNotEmpty()
12 | @Length(1, 64)
13 | cron: string
14 |
15 | @ApiProperty()
16 | @IsNotEmpty()
17 | @Length(1, 255)
18 | target: string
19 | }
20 |
--------------------------------------------------------------------------------
/server/src/website/dto/create-website.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsEnum, IsNotEmpty, IsString } from 'class-validator'
3 | import { DomainState } from 'src/gateway/entities/runtime-domain'
4 |
5 | export class CreateWebsiteDto {
6 | @ApiProperty()
7 | @IsNotEmpty()
8 | @IsString()
9 | bucketName: string
10 |
11 | @ApiProperty()
12 | @IsEnum(DomainState)
13 | @IsNotEmpty()
14 | state: DomainState
15 | }
16 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "./packages/*",
4 | "./docs",
5 | "./server",
6 | "./web",
7 | "./runtimes/nodejs",
8 | "./cli",
9 | "./services/*",
10 | "./e2e"
11 | ],
12 | "version": "1.0.0",
13 | "command": {
14 | "publish": {
15 | "ignoreChanges": [
16 | "package-lock.json",
17 | "*.md",
18 | "tests",
19 | "http",
20 | "ecosystem.config*"
21 | ]
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/server/src/region/region.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, Module } from '@nestjs/common'
2 | import { RegionService } from './region.service'
3 | import { RegionController } from './region.controller'
4 | import { ClusterService } from './cluster/cluster.service'
5 |
6 | @Global()
7 | @Module({
8 | providers: [RegionService, ClusterService],
9 | controllers: [RegionController],
10 | exports: [RegionService, ClusterService],
11 | })
12 | export class RegionModule {}
13 |
--------------------------------------------------------------------------------
/cli/src/action/storage/s3.ts:
--------------------------------------------------------------------------------
1 | import { S3Client } from '@aws-sdk/client-s3'
2 |
3 | export function getS3ClientV3(credentials: any): S3Client {
4 | return new S3Client({
5 | credentials: {
6 | accessKeyId: credentials.accessKeyId,
7 | secretAccessKey: credentials.accessKeySecret,
8 | sessionToken: credentials.sessionToken,
9 | },
10 | endpoint: credentials.endpoint,
11 | forcePathStyle: true,
12 | region: 'us-east-1',
13 | })
14 | }
15 |
--------------------------------------------------------------------------------
/server/src/log/entities/function-log.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class FunctionLog {
5 | @ApiProperty({ type: String })
6 | _id?: ObjectId
7 |
8 | @ApiProperty()
9 | request_id: string
10 |
11 | // cloud function name
12 | @ApiProperty()
13 | func: string
14 |
15 | // log content
16 | @ApiProperty()
17 | data: string
18 |
19 | @ApiProperty()
20 | created_at: Date
21 | }
22 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 云开发
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/web/src/pages/home/mods/Empty/index.module.scss:
--------------------------------------------------------------------------------
1 | .emptyItem {
2 | width: 230px;
3 | height: 78px;
4 |
5 | box-shadow: rgb(196 206 216 / 25%) 0px 4px 8px;
6 | border-radius: 24px 0px;
7 | margin-bottom: 24px;
8 | position: relative;
9 |
10 | &::before {
11 | content: " ";
12 | height: 10px;
13 | position: absolute;
14 | left: 20px;
15 | width: 4px;
16 | height: 16px;
17 | background: #00a99d;
18 | border-radius: 24px;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/docs/zh/cloud-storage/delete.md:
--------------------------------------------------------------------------------
1 |
2 | # 在云函数中删除文件
3 |
4 | ::: tip
5 | 在云函数中操作云存储,需要提前创建一个存储桶(Bucket),以下示例使用 `data` 存储桶演示上传文件操作,请提前创建该存储桶。
6 | :::
7 |
8 | ## 删除文件
9 |
10 | ```ts
11 | import cloud from '@lafjs/cloud'
12 |
13 | export default async function (ctx: FunctionContext) {
14 | // 获取存储桶
15 | const bucket = cloud.storage.bucket('data')
16 |
17 | // 删除文件
18 | await bucket.deleteFile('index.html')
19 | }
20 | ```
21 |
22 | ::: tip
23 | 注意:如果文件不存在,也会正常返回,不会抛出异常。
24 | :::
25 |
--------------------------------------------------------------------------------
/server/src/database/entities/collection.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { Binary, CollectionInfo, Document } from 'mongodb'
3 |
4 | export class Collection implements CollectionInfo {
5 | @ApiProperty()
6 | name: string
7 |
8 | @ApiProperty()
9 | type?: string
10 |
11 | @ApiProperty()
12 | options?: Document
13 |
14 | @ApiProperty()
15 | info?: { readOnly?: false; uuid?: Binary }
16 |
17 | @ApiProperty()
18 | idIndex?: Document
19 | }
20 |
--------------------------------------------------------------------------------
/services/runtime-exporter/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20.10.0
2 |
3 | # Set environment variables
4 | ENV LOG_LEVEL=debug
5 | ENV NODE_ENV=production
6 |
7 | WORKDIR /app
8 |
9 | COPY ./dist /app/dist
10 | COPY ./node_modules /app/node_modules
11 | COPY ./package*.json /app/
12 |
13 | # Set non-root user for better security
14 | RUN chown -R node:node /app
15 | USER node
16 |
17 | # Expose application port
18 | EXPOSE 2342
19 |
20 | # Start the application
21 | CMD [ "npm", "run", "start" ]
22 |
--------------------------------------------------------------------------------
/server/src/authentication/dto/github-bind.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator'
3 |
4 | export class GithubBind {
5 | @ApiProperty({ description: 'temporary token signed for github bindings' })
6 | @IsString()
7 | @IsNotEmpty()
8 | token: string
9 |
10 | @ApiProperty({ description: 'Is a newly registered use' })
11 | @IsBoolean()
12 | @IsOptional()
13 | isRegister: boolean
14 | }
15 |
--------------------------------------------------------------------------------
/server/src/gateway/entities/bucket-domain.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 | import { DomainPhase, DomainState } from './runtime-domain'
3 |
4 | export class BucketDomain {
5 | _id?: ObjectId
6 | appid: string
7 | bucketName: string
8 | domain: string
9 | state: DomainState
10 | phase: DomainPhase
11 | lockedAt: Date
12 | createdAt: Date
13 | updatedAt: Date
14 |
15 | constructor(partial: Partial) {
16 | Object.assign(this, partial)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/server/src/billing/entities/network-traffic.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export class Traffic {
4 | _id?: ObjectId
5 |
6 | timestamp: Date
7 |
8 | traffic_meta: TrafficMeta
9 |
10 | recv_bytes: number
11 |
12 | sent_bytes: number
13 | }
14 |
15 | export class TrafficMeta {
16 | pod_address: string
17 |
18 | pod_name: string
19 |
20 | pod_namespace: string
21 |
22 | pod_type: number
23 |
24 | pod_type_name: string
25 |
26 | traffic_tag: string
27 | }
28 |
--------------------------------------------------------------------------------
/server/src/dependency/dependency.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { ApplicationModule } from 'src/application/application.module'
3 | import { DependencyController } from './dependency.controller'
4 | import { DependencyService } from './dependency.service'
5 |
6 | @Module({
7 | imports: [ApplicationModule],
8 | controllers: [DependencyController],
9 | providers: [DependencyService],
10 | exports: [DependencyService],
11 | })
12 | export class DependencyModule {}
13 |
--------------------------------------------------------------------------------
/server/src/interceptor/dto/http-interceptor.dto.ts:
--------------------------------------------------------------------------------
1 | export enum HttpInterceptorAction {
2 | ALLOW = 'allow',
3 | DENY = 'deny',
4 | }
5 | class HttpInterceptorRewrite {
6 | status: number
7 | data: any
8 | }
9 | class HttpInterceptorRedirect {
10 | status: number
11 | data: string
12 | }
13 | export class HttpInterceptorResponseDto {
14 | action: HttpInterceptorAction
15 | rewrite?: HttpInterceptorRewrite
16 | redirect?: HttpInterceptorRedirect
17 | denyMessage?: string
18 | }
19 |
--------------------------------------------------------------------------------
/docs/.vitepress/en.mts:
--------------------------------------------------------------------------------
1 | import { DefaultTheme } from 'vitepress'
2 |
3 |
4 | export const NavItemsInEnglish: DefaultTheme.NavItem[] = [
5 | // { text: 'Guides', link: '/en/' },
6 | // { text: 'Examples', link: './markdown-examples' }
7 | ]
8 |
9 | export const SidebarItemsInEnglish: DefaultTheme.SidebarItem[] = [
10 | {
11 | text: 'Getting Started',
12 | items: [
13 | { text: 'Overview', link: '/en/' },
14 | { text: 'Architecture', link: '/en/architecture' },
15 | ]
16 | }
17 | ]
--------------------------------------------------------------------------------
/server/src/authentication/dto/email-verify-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export enum EmailVerifyCodeType {
4 | Bind = 'bind',
5 | Unbind = 'Unbind',
6 | }
7 |
8 | export enum EmailVerifyCodeState {
9 | Unused = 0,
10 | Used = 1,
11 | }
12 |
13 | export class EmailVerifyCode {
14 | _id?: ObjectId
15 | email: string
16 | code: string
17 | ip: string
18 | type: EmailVerifyCodeType
19 | state: EmailVerifyCodeState
20 | createdAt: Date
21 | updatedAt: Date
22 | }
23 |
--------------------------------------------------------------------------------
/server/src/user/dto/create-pat.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import {
3 | IsNotEmpty,
4 | IsNumber,
5 | IsString,
6 | Length,
7 | Max,
8 | Min,
9 | } from 'class-validator'
10 |
11 | export class CreatePATDto {
12 | @IsString()
13 | @IsNotEmpty()
14 | @Length(1, 255)
15 | @ApiProperty()
16 | name: string
17 |
18 | @IsNumber()
19 | @IsNotEmpty()
20 | @Min(60)
21 | @Max(3600 * 24 * 365)
22 | @ApiProperty({ minimum: 60 })
23 | expiresIn: number
24 | }
25 |
--------------------------------------------------------------------------------
/runtimes/nodejs/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ln -s $CUSTOM_DEPENDENCY_BASE_PATH/node_modules $PWD/functions/node_modules >/dev/null 2>&1
4 |
5 | # generate package.json
6 | # (
7 | # cd $CUSTOM_DEPENDENCY_BASE_PATH
8 | # npm install $DEPENDENCIES $NPM_INSTALL_FLAGS > /dev/null 2>&1
9 | # )
10 |
11 | # source .env
12 | echo "****** start service: node $FLAGS --experimental-vm-modules --experimental-fetch ./dist/index.js *******"
13 | exec node $FLAGS --experimental-vm-modules --experimental-fetch ./dist/index.js
14 |
--------------------------------------------------------------------------------
/cli/src/util/format.ts:
--------------------------------------------------------------------------------
1 | import * as dayjs from 'dayjs'
2 |
3 | export function formatDate(
4 | date?: string | number | Date | dayjs.Dayjs | null | undefined,
5 | format = 'YYYY-MM-DD HH:mm:ss',
6 | ) {
7 | return dayjs(date).format(format)
8 | }
9 |
10 | export function formatSize(size: number) {
11 | const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
12 | let i = 0
13 | while (size >= 1024) {
14 | size /= 1024
15 | i++
16 | }
17 | return size.toFixed(2) + ' ' + units[i]
18 | }
19 |
--------------------------------------------------------------------------------
/packages/database-proxy/tests/units/accessor.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert')
2 | const { MongoAccessor } = require('../../dist')
3 |
4 | const { MongoClient, Db } = require('mongodb')
5 |
6 | describe('db-proxy(unit): class Accessor', () => {
7 | it('constructor() ok', () => {
8 | const client = new MongoClient('mongodb://localhost:27017/test-db')
9 | const acc = new MongoAccessor(client)
10 | assert.ok(acc.db instanceof Db)
11 | assert.ok(acc.client instanceof MongoClient)
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/runtimes/nodejs/build-image.sh:
--------------------------------------------------------------------------------
1 |
2 | # Warning: just for development phase, will be move to github action in future.
3 |
4 | # get version from package.json
5 | version=$(node -p "require('./package.json').version")
6 |
7 | # build main image
8 | docker buildx build --platform linux/amd64,linux/arm64 --push -t docker.io/lafyun/runtime-node:$version -f Dockerfile .
9 |
10 | # build init image
11 | docker buildx build --platform linux/amd64,linux/arm64 --push -t docker.io/lafyun/runtime-node-init:$version -f Dockerfile.init .
--------------------------------------------------------------------------------
/server/src/account/entities/account-charge-reward.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class AccountChargeReward {
5 | @ApiProperty({ type: String })
6 | _id?: ObjectId
7 |
8 | @ApiProperty()
9 | amount: number
10 |
11 | @ApiProperty({})
12 | reward: number
13 |
14 | @ApiPropertyOptional()
15 | message?: string
16 |
17 | @ApiProperty()
18 | createdAt: Date
19 |
20 | @ApiProperty()
21 | updatedAt: Date
22 | }
23 |
--------------------------------------------------------------------------------
/runtimes/nodejs/src/constants.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Collection names
3 | */
4 | export const CLOUD_FUNCTION_COLLECTION = '__functions__'
5 | export const POLICY_COLLECTION = '__policies__'
6 | export const CONFIG_COLLECTION = '__conf__'
7 | export const WEBSITE_HOSTING_COLLECTION = '__website_hosting__'
8 |
9 | export const WEBSOCKET_FUNCTION_NAME = '__websocket__'
10 | export const INTERCEPTOR_FUNCTION_NAME = '__interceptor__'
11 | export const DEFAULT_FUNCTION_NAME = '__default__'
12 | export const INIT_FUNCTION_NAME = '__init__'
13 |
--------------------------------------------------------------------------------
/server/src/i18n/en/function.json:
--------------------------------------------------------------------------------
1 | {
2 | "create": {
3 | "nameExist": "function {name} is already existed",
4 | "maxCount": "function count limit is {max}",
5 | "error": "create function error"
6 | },
7 | "get": {},
8 | "update": {
9 | "error": "update function error"
10 | },
11 | "delete": {
12 | "error": "delete function error"
13 | },
14 | "compile": {
15 | "codeRequired": "code is required"
16 | },
17 | "common": {
18 | "notFound": "function {name} is not found"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/server/src/monitor/monitor.module.ts:
--------------------------------------------------------------------------------
1 | import { HttpModule } from '@nestjs/axios'
2 | import { Module } from '@nestjs/common'
3 | import { MonitorController } from './monitor.controller'
4 | import { MonitorService } from './monitor.service'
5 | import { ApplicationModule } from 'src/application/application.module'
6 |
7 | @Module({
8 | imports: [HttpModule, ApplicationModule],
9 | controllers: [MonitorController],
10 | providers: [MonitorService],
11 | exports: [MonitorService],
12 | })
13 | export class MonitorModule {}
14 |
--------------------------------------------------------------------------------
/web/public/homepage/icon_02.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/web/src/pages/app/setting/UserSetting/CardRedemption/service.ts:
--------------------------------------------------------------------------------
1 | import { useMutation } from "@tanstack/react-query";
2 |
3 | import { AccountControllerGiftCode } from "@/apis/v1/accounts";
4 |
5 | export const useGiftCodeMutation = (config?: { onSuccess: (result: any) => void }) => {
6 | return useMutation(
7 | (values: any) => {
8 | return AccountControllerGiftCode(values);
9 | },
10 | {
11 | onSuccess: async (result) => {
12 | config?.onSuccess(result);
13 | },
14 | },
15 | );
16 | };
17 |
--------------------------------------------------------------------------------
/e2e/9-cleaning/00-clean.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, test } from '@jest/globals'
2 | import { ClearTestApplications, ClearTestUser } from '../api'
3 | import { Config } from '../config'
4 |
5 | describe('cleaning', () => {
6 | test(
7 | 'clear testing applications',
8 | async () => {
9 | await ClearTestApplications()
10 | },
11 | 10 * 1000
12 | )
13 |
14 | test(
15 | 'clear testing user',
16 | async () => {
17 | await ClearTestUser(Config.TEST_USERNAME)
18 | },
19 | 10 * 1000
20 | )
21 | })
22 |
--------------------------------------------------------------------------------
/server/src/function-template/dto/use-function-template.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString, Length } from 'class-validator'
3 | import { ObjectId } from 'mongodb'
4 |
5 | export class UseFunctionTemplateDto {
6 | @ApiProperty({
7 | description: 'The ObjectId of function template',
8 | type: 'string',
9 | })
10 | @IsNotEmpty()
11 | @Length(24, 24)
12 | functionTemplateId: ObjectId
13 |
14 | @ApiProperty()
15 | @IsString()
16 | @IsNotEmpty()
17 | appid: string
18 | }
19 |
--------------------------------------------------------------------------------
/web/src/pages/home/mods/CreateAppModal/RuntimeItem/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { CheckIcon } from "@chakra-ui/icons";
3 |
4 | import { TBundle } from "@/apis/typing";
5 |
6 | export default function RuntimeItem(props: { bundle?: TBundle }) {
7 | return (
8 |
9 |
10 |

- latest
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/server/src/authentication/entities/types.ts:
--------------------------------------------------------------------------------
1 | export enum AuthBindingType {
2 | Required = 'required',
3 | Optional = 'optional',
4 | None = 'none',
5 | }
6 |
7 | export interface AuthProviderBinding {
8 | username: AuthBindingType
9 | phone: AuthBindingType
10 | email: AuthBindingType
11 | github: AuthBindingType
12 | wechat: AuthBindingType
13 | }
14 |
15 | export interface AlismsConfig {
16 | accessKeyId: string
17 | accessKeySecret: string
18 | endpoint: string
19 | signName: string
20 | templateCode: string
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/initializer/deploy-manifest/databaseOpsRequestHorizontalScaling.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps.kubeblocks.io/v1alpha1
2 | kind: OpsRequest
3 | metadata:
4 | labels:
5 | app.kubernetes.io/instance: <%- clusterName %>
6 | ops.kubeblocks.io/ops-type: HorizontalScaling
7 | sealos-db-provider-cr: <%- clusterName %>
8 | name: <%- name %>
9 | namespace: laf-system
10 | spec:
11 | clusterRef: <%- clusterName %>
12 | horizontalScaling:
13 | - componentName: mongodb
14 | replicas: <%- replicas %>
15 | type: HorizontalScaling
16 |
--------------------------------------------------------------------------------
/server/src/authentication/dto/send-email-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsEmail, IsEnum, IsNotEmpty } from 'class-validator'
3 | import { EmailVerifyCodeType } from '../entities/email-verify-code'
4 |
5 | export class SendEmailCodeDto {
6 | @ApiProperty()
7 | @IsEmail()
8 | @IsNotEmpty()
9 | email: string
10 |
11 | @ApiProperty({
12 | description: 'verify code type',
13 | enum: EmailVerifyCodeType,
14 | })
15 | @IsNotEmpty()
16 | @IsEnum(EmailVerifyCodeType)
17 | type: EmailVerifyCodeType
18 | }
19 |
--------------------------------------------------------------------------------
/server/src/log/log.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { JwtService } from '@nestjs/jwt'
3 | import { DatabaseModule } from 'src/database/database.module'
4 | import { FunctionModule } from 'src/function/function.module'
5 | import { ApplicationModule } from '../application/application.module'
6 | import { LogController } from './log.controller'
7 |
8 | @Module({
9 | imports: [ApplicationModule, FunctionModule, DatabaseModule],
10 | controllers: [LogController],
11 | providers: [JwtService],
12 | })
13 | export class LogModule {}
14 |
--------------------------------------------------------------------------------
/web/src/pages/app/functions/mods/FunctionPanel/ContextMenu/index.scss:
--------------------------------------------------------------------------------
1 | .contexify {
2 | box-shadow: none !important;
3 | border: 1px solid #e2e8f0 !important;
4 | min-width: 0 !important;
5 | justify-content: center;
6 | width: 120px;
7 | padding: 2px !important;
8 | }
9 |
10 | .contexify_theme-dark {
11 | background-color: #212630 !important;
12 | border: 1px solid rgba(255, 255, 255, 0.16) !important;
13 | }
14 |
15 | .contexify_itemContent {
16 | background: none !important;
17 | width: 100% !important;
18 | height: 100% !important;
19 | }
--------------------------------------------------------------------------------
/web/src/pages/homepage/homepage.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | .homepage {
6 | -webkit-font-smoothing: auto;
7 | }
8 |
9 | @layer base {
10 | h1 {
11 | @apply text-center font-bold;
12 | }
13 | h2 {
14 | @apply text-center text-3xl font-semibold;
15 | }
16 | h3 {
17 | @apply text-3xl font-medium;
18 | }
19 | }
20 |
21 | .bg-card {
22 | background-color: #f9f9f9;
23 | }
24 |
25 | .bg-primary {
26 | background-color: #00beb1;
27 | }
28 |
29 | a:hover {
30 | opacity: 0.8;
31 | }
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 |
4 | upload
5 | data/*
6 | tmp
7 |
8 | ecosystem.config.js
9 | .DS_Store
10 | .idea
11 |
12 | coverage
13 | .nyc_output
14 |
15 | kubernetes-dev/mongo-data
16 |
17 | kubernetes-local/
18 | .vscode/configurationCache.log
19 | .vscode/dryrun.log
20 | .vscode/targets.log
21 |
22 | .kube/
23 |
24 | build/*/manifests
25 | build/*/registry
26 | build/*/charts
27 | build/registry
28 | build-dev
29 | docs/.vitepress/.temp
30 | .idea/
31 |
32 | update-changelog.sh
33 | runtimes/nodejs-esm
34 | yarn.lock
35 | deploy/logs/sealos.log
36 |
--------------------------------------------------------------------------------
/packages/client-sdk/tests/http/read_test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert')
2 | const client = require('../../dist/commonjs/index')
3 | const config = require('./config')
4 |
5 | describe('client-sdk(http): db.get()', function () {
6 | it('read empty should be ok', async () => {
7 | const cloud = client.init({
8 | dbProxyUrl: config.dbProxyUrl,
9 | getAccessToken: config.getAccessToken,
10 | })
11 |
12 | const res = await cloud.database().collection('categories').get()
13 |
14 | assert.ok(res.data instanceof Array)
15 | })
16 | })
17 |
--------------------------------------------------------------------------------
/server/src/region/cluster/cluster.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing'
2 | import { ClusterService } from './cluster.service'
3 |
4 | describe('ClusterService', () => {
5 | let service: ClusterService
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [ClusterService],
10 | }).compile()
11 |
12 | service = module.get(ClusterService)
13 | })
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined()
17 | })
18 | })
19 |
--------------------------------------------------------------------------------
/server/src/account/dto/invite-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class InviteCodeProfit {
5 | @ApiProperty({ type: String })
6 | _id: ObjectId
7 |
8 | @ApiProperty({ type: String })
9 | uid: ObjectId
10 |
11 | @ApiProperty({ type: String })
12 | invitedBy: ObjectId
13 |
14 | @ApiProperty({ type: String })
15 | codeId: ObjectId
16 |
17 | @ApiProperty()
18 | createdAt: Date
19 |
20 | @ApiProperty()
21 | profit: number
22 |
23 | @ApiProperty()
24 | username: string
25 | }
26 |
--------------------------------------------------------------------------------
/server/src/application/events/application-creating.event.ts:
--------------------------------------------------------------------------------
1 | import { ClientSession } from 'mongodb'
2 | import { CreateApplicationDto } from '../dto/create-application.dto'
3 | import { Region } from 'src/region/entities/region'
4 |
5 | export class ApplicationCreatingEvent {
6 | region: Region
7 | appid: string
8 | session: ClientSession
9 | dto: CreateApplicationDto
10 |
11 | constructor(partial: Partial) {
12 | Object.assign(this, partial)
13 | }
14 |
15 | static get eventName() {
16 | return 'application.creating'
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | pnpm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 |
14 | # OS
15 | .DS_Store
16 |
17 | # Tests
18 | /coverage
19 | /.nyc_output
20 |
21 | # IDEs and editors
22 | /.idea
23 | .project
24 | .classpath
25 | .c9/
26 | *.launch
27 | .settings/
28 | *.sublime-workspace
29 |
30 | # IDE - VSCode
31 | .vscode/*
32 | !.vscode/settings.json
33 | !.vscode/tasks.json
34 | !.vscode/launch.json
35 | !.vscode/extensions.json
36 |
37 | .env.local
38 | .env
39 |
--------------------------------------------------------------------------------
/server/src/authentication/dto/passwd-signin.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsString, Length } from 'class-validator'
3 |
4 | export class PasswdSigninDto {
5 | @ApiProperty({
6 | description: 'username',
7 | example: 'laf-user',
8 | })
9 | @IsString()
10 | @IsNotEmpty()
11 | @Length(3, 64)
12 | username: string
13 |
14 | @ApiProperty({
15 | description: 'password, 8-64 characters',
16 | example: 'laf-user-password',
17 | })
18 | @IsString()
19 | @IsNotEmpty()
20 | @Length(8, 64)
21 | password: string
22 | }
23 |
--------------------------------------------------------------------------------
/server/src/authentication/entities/email-verify-code.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export enum EmailVerifyCodeType {
4 | Signin = 'Signin',
5 | Signup = 'Signup',
6 | ResetPassword = 'ResetPassword',
7 | Bind = 'bind',
8 | Unbind = 'Unbind',
9 | }
10 |
11 | export enum EmailVerifyCodeState {
12 | Unused = 0,
13 | Used = 1,
14 | }
15 |
16 | export class EmailVerifyCode {
17 | _id?: ObjectId
18 | email: string
19 | code: string
20 | ip: string
21 | type: EmailVerifyCodeType
22 | state: EmailVerifyCodeState
23 | createdAt: Date
24 | updatedAt: Date
25 | }
26 |
--------------------------------------------------------------------------------
/server/src/website/website.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { WebsiteService } from './website.service'
3 | import { WebsiteController } from './website.controller'
4 | import { ApplicationService } from 'src/application/application.service'
5 | import { StorageModule } from 'src/storage/storage.module'
6 | import { BundleService } from 'src/application/bundle.service'
7 |
8 | @Module({
9 | imports: [StorageModule],
10 | controllers: [WebsiteController],
11 | providers: [WebsiteService, ApplicationService, BundleService],
12 | })
13 | export class WebsiteModule {}
14 |
--------------------------------------------------------------------------------
/cli/src/api/custom.ts:
--------------------------------------------------------------------------------
1 | import { request } from '../util/request'
2 |
3 | export async function databaseControllerExport(appid: string): Promise {
4 | return request({
5 | url: `/v1/apps/${appid}/databases/export`,
6 | method: 'GET',
7 | responseType: 'stream',
8 | })
9 | }
10 |
11 | export async function databaseControllerImport(appid: string, data: any): Promise {
12 | return request({
13 | url: `/v1/apps/${appid}/databases/import`,
14 | method: 'PUT',
15 | data: data,
16 | headers: {
17 | 'Content-Type': 'multipart/form-data',
18 | },
19 | })
20 | }
21 |
--------------------------------------------------------------------------------
/server/src/group/dto/get-group-invite-code-detail.dto.ts:
--------------------------------------------------------------------------------
1 | import { OmitType } from '@nestjs/mapped-types'
2 | import { GroupInviteCode } from '../entities/group-invite-code'
3 | import { Group } from '../entities/group'
4 | import { ApiProperty } from '@nestjs/swagger'
5 | import { User } from 'src/user/entities/user'
6 |
7 | export class GetGroupInviteCodeDetailDto extends OmitType(GroupInviteCode, [
8 | 'groupId',
9 | '_id',
10 | 'createdBy',
11 | 'groupId',
12 | ]) {
13 | @ApiProperty({ type: Group })
14 | group: Group
15 |
16 | @ApiProperty({ type: User })
17 | invitedBy: User
18 | }
19 |
--------------------------------------------------------------------------------
/server/src/initializer/deploy-manifest/databaseOpsRequestVolumeExpansion.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps.kubeblocks.io/v1alpha1
2 | kind: OpsRequest
3 | metadata:
4 | labels:
5 | app.kubernetes.io/instance: <%- clusterName %>
6 | ops.kubeblocks.io/ops-type: VolumeExpansion
7 | sealos-db-provider-cr: <%- clusterName %>
8 | name: <%- name %>
9 | namespace: laf-system
10 | spec:
11 | clusterRef: <%- clusterName %>
12 | type: VolumeExpansion
13 | volumeExpansion:
14 | - componentName: mongodb
15 | volumeClaimTemplates:
16 | - name: data
17 | storage: <%- capacity %>Gi
18 |
--------------------------------------------------------------------------------
/web/src/components/Panel/index.module.scss:
--------------------------------------------------------------------------------
1 | .sectionHeader {
2 | min-height: 32px;
3 | max-height: 32px;
4 | display: flex;
5 | align-items: center;
6 |
7 | h4 {
8 | padding-left: 10px;
9 | font-weight: 500;
10 | font-size: 12px;
11 | position: relative;
12 |
13 | &::before {
14 | content: " ";
15 | height: 12px;
16 | position: absolute;
17 | left: 0;
18 | top: 3px;
19 | width: 3px;
20 | background: #00a99d;
21 | border-radius: 24px;
22 | }
23 | }
24 |
25 | h4 svg {
26 | vertical-align: -4px !important;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/web/src/hooks/useDB.ts:
--------------------------------------------------------------------------------
1 | import { Cloud } from "laf-client-sdk";
2 |
3 | import { VITE_SERVER_BASE_URL } from "../constants";
4 |
5 | import useGlobalStore from "@/pages/globalStore";
6 |
7 | function useDB() {
8 | const currentApp = useGlobalStore((state) => state.currentApp);
9 | const dbm_cloud = new Cloud({
10 | baseUrl: VITE_SERVER_BASE_URL,
11 | dbProxyUrl: `/v1/apps/${currentApp?.appid}/databases/proxy`,
12 | getAccessToken: () => localStorage.getItem("token") as any,
13 | });
14 |
15 | const db = dbm_cloud.database();
16 |
17 | return { db };
18 | }
19 |
20 | export default useDB;
21 |
--------------------------------------------------------------------------------
/server/src/application/events/application-bundle-updating.event.ts:
--------------------------------------------------------------------------------
1 | import { ClientSession } from 'mongodb'
2 | import { Region } from 'src/region/entities/region'
3 | import { UpdateApplicationBundleDto } from '../dto/update-application.dto'
4 |
5 | export class ApplicationBundleUpdatingEvent {
6 | region: Region
7 | appid: string
8 | session: ClientSession
9 | dto: UpdateApplicationBundleDto
10 |
11 | constructor(partial: Partial) {
12 | Object.assign(this, partial)
13 | }
14 |
15 | static get eventName() {
16 | return 'application.bundle.updating'
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/web/src/components/IconText/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import clsx from "clsx";
3 |
4 | import styles from "./index.module.scss";
5 |
6 | export default function IconText(props: {
7 | icon: React.ReactElement;
8 | text: string;
9 | className?: string;
10 | onClick?: () => void;
11 | }) {
12 | return (
13 |
17 | {React.cloneElement(props.icon, {
18 | height: "20px",
19 | })}
20 | {props.text}
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/e2e/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "laf-testing",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "",
6 | "scripts": {
7 | "test": "jest",
8 | "lint": "eslint . --fix --ext .ts --ext .js"
9 | },
10 | "keywords": [],
11 | "author": "",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "@jest/globals": "^29.6.2",
15 | "@types/jest": "^29.5.3",
16 | "ts-jest": "^29.1.1"
17 | },
18 | "dependencies": {
19 | "axios": "^1.4.0",
20 | "dotenv": "^16.3.1",
21 | "mongodb": "^5.7.0"
22 | },
23 | "lint-staged": {
24 | "*.{ts,js}": "eslint --fix"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/server/src/authentication/entities/sms-verify-code.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export enum SmsVerifyCodeType {
4 | Signin = 'Signin',
5 | Signup = 'Signup',
6 | ResetPassword = 'ResetPassword',
7 | Bind = 'Bind',
8 | Unbind = 'Unbind',
9 | ChangePhone = 'ChangePhone',
10 | }
11 |
12 | export enum SmsVerifyCodeState {
13 | Unused = 0,
14 | Used = 1,
15 | }
16 |
17 | export class SmsVerifyCode {
18 | _id?: ObjectId
19 | phone: string
20 | code: string
21 | ip: string
22 | type: SmsVerifyCodeType
23 | state: SmsVerifyCodeState
24 | createdAt: Date
25 | updatedAt: Date
26 | }
27 |
--------------------------------------------------------------------------------
/server/src/trigger/entities/cron-trigger.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export enum TriggerState {
4 | Active = 'Active',
5 | Inactive = 'Inactive',
6 | Deleted = 'Deleted',
7 | }
8 |
9 | export enum TriggerPhase {
10 | Creating = 'Creating',
11 | Created = 'Created',
12 | Deleting = 'Deleting',
13 | Deleted = 'Deleted',
14 | }
15 |
16 | export class CronTrigger {
17 | _id?: ObjectId
18 | appid: string
19 | desc: string
20 | cron: string
21 | target: string
22 | state: TriggerState
23 | phase: TriggerPhase
24 | lockedAt: Date
25 | createdAt: Date
26 | updatedAt: Date
27 | }
28 |
--------------------------------------------------------------------------------
/server/src/database/dto/create-dedicated-database.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsInt, IsNotEmpty, Max } from 'class-validator'
3 |
4 | export class CreateDedicatedDatabaseDto {
5 | @ApiProperty({ example: 200 })
6 | @IsNotEmpty()
7 | @IsInt()
8 | cpu: number
9 |
10 | @ApiProperty({ example: 256 })
11 | @IsNotEmpty()
12 | @IsInt()
13 | memory: number
14 |
15 | @ApiProperty({ example: 1024 })
16 | @IsNotEmpty()
17 | @IsInt()
18 | capacity: number
19 |
20 | @ApiProperty({ example: 3 })
21 | @IsNotEmpty()
22 | @IsInt()
23 | @Max(9)
24 | replicas: number
25 | }
26 |
--------------------------------------------------------------------------------
/server/src/user/entities/pat.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 | import { User } from './user'
3 | import { ApiProperty } from '@nestjs/swagger'
4 |
5 | export class PersonalAccessToken {
6 | @ApiProperty({ type: String })
7 | _id?: ObjectId
8 |
9 | @ApiProperty({ type: String })
10 | uid: ObjectId
11 |
12 | @ApiProperty()
13 | name: string
14 |
15 | token: string
16 |
17 | @ApiProperty()
18 | expiredAt: Date
19 |
20 | @ApiProperty()
21 | createdAt: Date
22 | }
23 |
24 | export class PersonalAccessTokenWithUser extends PersonalAccessToken {
25 | @ApiProperty({ type: User })
26 | user: User
27 | }
28 |
--------------------------------------------------------------------------------
/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": false,
16 | "noImplicitAny": false,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": false,
19 | "noFallthroughCasesInSwitch": false
20 | }
21 | }
--------------------------------------------------------------------------------
/server/src/instance/instance.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { InstanceService } from './instance.service'
3 | import { InstanceTaskService } from './instance-task.service'
4 | import { StorageModule } from '../storage/storage.module'
5 | import { DatabaseModule } from '../database/database.module'
6 | import { ApplicationModule } from 'src/application/application.module'
7 | import { JwtService } from '@nestjs/jwt'
8 |
9 | @Module({
10 | imports: [StorageModule, DatabaseModule, ApplicationModule],
11 | providers: [InstanceService, InstanceTaskService, JwtService],
12 | })
13 | export class InstanceModule {}
14 |
--------------------------------------------------------------------------------
/cli/src/common/wait.ts:
--------------------------------------------------------------------------------
1 | import { applicationControllerFindOne } from '../api/v1/application'
2 | import { AppSchema } from '../schema/app'
3 |
4 | const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))
5 |
6 | const interval = 2000 // interval 1000ms
7 | export async function waitApplicationState(targetState: string) {
8 | const appSchema = AppSchema.read()
9 | while (true) {
10 | const app = await applicationControllerFindOne(appSchema.appid)
11 | if (app.state === targetState) {
12 | return
13 | }
14 | sleep(interval)
15 | console.log(`application waiting ${targetState}....`)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": false,
16 | "noImplicitAny": false,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": false,
19 | "noFallthroughCasesInSwitch": false
20 | }
21 | }
--------------------------------------------------------------------------------
/server/src/group/entities/group.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 | import { GroupRole } from './group-member'
3 | import { ApiProperty } from '@nestjs/swagger'
4 |
5 | export class Group {
6 | @ApiProperty({ type: String })
7 | _id?: ObjectId
8 |
9 | @ApiProperty()
10 | name: string
11 |
12 | @ApiProperty()
13 | appid?: string
14 |
15 | @ApiProperty({ type: String })
16 | createdBy: ObjectId
17 |
18 | @ApiProperty()
19 | createdAt: Date
20 |
21 | @ApiProperty()
22 | updatedAt: Date
23 | }
24 |
25 | export class GroupWithRole extends Group {
26 | @ApiProperty({ enum: GroupRole })
27 | role: GroupRole
28 | }
29 |
--------------------------------------------------------------------------------
/server/src/application/dto/pod.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsNotEmpty, IsArray, IsString } from 'class-validator'
3 |
4 | export class PodNameListDto {
5 | @ApiProperty()
6 | appid: string
7 |
8 | @ApiProperty({
9 | description: 'List of pod identifiers',
10 | example: ['pod1', 'pod2'],
11 | })
12 | podNameList: string[]
13 | }
14 |
15 | export class ContainerNameListDto {
16 | @ApiProperty()
17 | podName: string
18 |
19 | @ApiProperty({
20 | description: 'List of container identifiers',
21 | example: ['container1', 'container2'],
22 | })
23 | containerNameList: string[]
24 | }
25 |
--------------------------------------------------------------------------------
/packages/node-modules-utils/tests/cloud-sdk.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert')
2 | const path = require('path')
3 | const { PackageDeclaration } = require('../dist')
4 |
5 | const nmp = path.resolve(__dirname, '../../app-service/node_modules')
6 |
7 | describe('npm-util(unit): Package Declaration Load', () => {
8 | /**
9 | * load from self package: @
10 | */
11 | it('load d.ts of @ (typings)', async () => {
12 | const pkg = new PackageDeclaration('@', nmp)
13 | await pkg.load()
14 | // console.log(pkg.declarations)
15 |
16 | assert.strictEqual(pkg.name, '@')
17 | assert.ok(pkg.declarations.length > 0)
18 | })
19 | })
20 |
--------------------------------------------------------------------------------
/server/src/account/account.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { AccountService } from './account.service'
3 | import { AccountController } from './account.controller'
4 | import { WeChatPayService } from './payment/wechat-pay.service'
5 | import { PaymentChannelService } from './payment/payment-channel.service'
6 | import { HttpModule } from '@nestjs/axios'
7 |
8 | @Module({
9 | imports: [HttpModule],
10 | providers: [AccountService, WeChatPayService, PaymentChannelService],
11 | controllers: [AccountController],
12 | exports: [WeChatPayService, AccountService, PaymentChannelService],
13 | })
14 | export class AccountModule {}
15 |
--------------------------------------------------------------------------------
/packages/database-proxy/src/validators/index.ts:
--------------------------------------------------------------------------------
1 | import { ConditionHandler } from './condition'
2 | import { DataHandler } from './data'
3 | import { QueryHandler } from './query'
4 | import { MultiHandler } from './multi'
5 | import { JoinHandler } from './join'
6 | import { LookupHandler } from './lookup'
7 |
8 | export const condition = ConditionHandler
9 | export const cond = ConditionHandler // alias of condition
10 |
11 | export const data = DataHandler
12 | export const schema = DataHandler // alias of data
13 | export const query = QueryHandler
14 | export const multi = MultiHandler
15 | export const join = JoinHandler
16 | export const lookup = LookupHandler
17 |
--------------------------------------------------------------------------------
/server/src/notification/notification.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, Module } from '@nestjs/common'
2 | import { NotificationService } from './notification.service'
3 | import { NotificationTaskService } from './notification-task.service'
4 | import { NotificationController } from './notification.controller'
5 | import { HttpModule } from '@nestjs/axios'
6 | import { UserModule } from 'src/user/user.module'
7 |
8 | @Global()
9 | @Module({
10 | providers: [NotificationService, NotificationTaskService],
11 | exports: [NotificationService],
12 | controllers: [NotificationController],
13 | imports: [HttpModule, UserModule],
14 | })
15 | export class NotificationModule {}
16 |
--------------------------------------------------------------------------------
/web/public/homepage/logo_icon.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/packages/database-ql/tests/units/get/orderby.test.js:
--------------------------------------------------------------------------------
1 | const { getDb } = require('../_utils')
2 | const assert = require('assert')
3 |
4 | describe('db-ql(unit): db::orderBy()', () => {
5 | it('orderBy() should be ok', async () => {
6 | const { db, req } = getDb()
7 | const res = await db
8 | .collection('tasks')
9 | .orderBy('age', 'asc')
10 | .orderBy('score', 'desc')
11 | .get()
12 |
13 | assert.ok(req.params.order.length === 2)
14 | assert.deepEqual(req.params.order[0], { field: 'age', direction: 'asc' })
15 | assert.deepEqual(req.params.order[1], {
16 | field: 'score',
17 | direction: 'desc',
18 | })
19 | })
20 | })
21 |
--------------------------------------------------------------------------------
/packages/database-proxy/docs/ruler_v2_design.md:
--------------------------------------------------------------------------------
1 |
2 | ## 关于访问规则重新设计的讨论
3 |
4 | 1. query 重定义
5 | 2. 支持 $schema 定义
6 | 3. 将 data 验证器中对 add 和 update 操作的逻辑拆分
7 | 4. data-update 不需要 required 和 default
8 |
9 | > 重点研究 query,核心安全控制在于 query;
10 |
11 | ### data.add
12 |
13 | 1. data 中不包含任何操作符
14 | 2. 不需要 merge 选项
15 | 3. 配置为数组时,限定只允许写入数组中指定的字段
16 | 4. data.add 即 schema,考虑两者之间的关系
17 |
18 | ### data.update
19 |
20 | 1. 默认 merge == true 为 update, merge == false 时为 set(replace)
21 | 2. update 时有 $set $unset $push $inc 等操作符
22 | 3. data.update: update & set 做区分
23 |
24 | ### data.add data.update schema
25 |
26 | 1. 可考虑弱化 data.add data.update 的用法
27 | 2. schema 还是 data 的别名实现,schema 可同时作用于 udpate & add
--------------------------------------------------------------------------------
/server/src/function/entities/cloud-function-history.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class CloudFunctionHistorySource {
5 | @ApiProperty()
6 | code: string
7 | }
8 |
9 | export class CloudFunctionHistory {
10 | @ApiProperty({ type: String })
11 | _id?: ObjectId
12 |
13 | @ApiProperty()
14 | appid: string
15 |
16 | @ApiProperty({ type: String })
17 | functionId: ObjectId
18 |
19 | @ApiProperty({ type: CloudFunctionHistorySource })
20 | source: CloudFunctionHistorySource
21 |
22 | @ApiProperty({ type: String })
23 | changelog?: string
24 |
25 | @ApiProperty()
26 | createdAt: Date
27 | }
28 |
--------------------------------------------------------------------------------
/cli/src/api/v1/monitor.ts:
--------------------------------------------------------------------------------
1 | import { request, RequestParams } from '../../util/request'
2 | import { MonitorControllerGetDataParams } from './data-contracts'
3 |
4 | /**
5 | * No description
6 | *
7 | * @tags Monitor
8 | * @name MonitorControllerGetData
9 | * @summary Get monitor metrics data
10 | * @request GET:/v1/monitor/{appid}/metrics
11 | * @secure
12 | */
13 | export async function monitorControllerGetData(
14 | { appid, ...query }: MonitorControllerGetDataParams,
15 | configParams: RequestParams = {},
16 | ): Promise {
17 | return request({
18 | url: `/v1/monitor/${appid}/metrics`,
19 | method: 'GET',
20 | params: query,
21 | ...configParams,
22 | })
23 | }
24 |
--------------------------------------------------------------------------------
/server/src/initializer/deploy-manifest/databaseOpsRequestVerticalScaling.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps.kubeblocks.io/v1alpha1
2 | kind: OpsRequest
3 | metadata:
4 | labels:
5 | app.kubernetes.io/instance: <%- clusterName %>
6 | ops.kubeblocks.io/ops-type: VerticalScaling
7 | sealos-db-provider-cr: <%- clusterName %>
8 | name: <%- name %>
9 | namespace: laf-system
10 | spec:
11 | clusterRef: <%- clusterName %>
12 | type: VerticalScaling
13 | verticalScaling:
14 | - componentName: mongodb
15 | limits:
16 | cpu: <%- limitCPU %>m
17 | memory: <%- limitMemory %>Mi
18 | requests:
19 | cpu: <%- requestCPU %>m
20 | memory: <%- requestMemory %>Mi
21 |
--------------------------------------------------------------------------------
/web/src/pages/app/database/CollectionDataList/mods/ColPanel/index.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@chakra-ui/react";
2 | import { t } from "i18next";
3 |
4 | import JSONEditor from "@/components/Editor/JSONEditor";
5 | export default function ColPanel() {
6 | return (
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/packages/database-ql/src/serverDate/index.ts:
--------------------------------------------------------------------------------
1 | import { SYMBOL_SERVER_DATE } from '../helper/symbol'
2 |
3 | export class ServerDate {
4 | readonly offset: number
5 |
6 | constructor({ offset = 0 } = {}) {
7 | this.offset = offset
8 | }
9 |
10 | get _internalType() {
11 | return SYMBOL_SERVER_DATE
12 | }
13 |
14 | parse() {
15 | return {
16 | $date: {
17 | offset: this.offset,
18 | },
19 | }
20 | }
21 | }
22 |
23 | /**
24 | * @deprecated This method is deprecated, not implemented in server side
25 | * @param opt
26 | * @returns
27 | */
28 | export function ServerDateConstructor(opt?: { offset: number }) {
29 | return new ServerDate(opt)
30 | }
31 |
--------------------------------------------------------------------------------
/server/src/storage/dto/create-bucket.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsEnum, IsNotEmpty, Matches } from 'class-validator'
3 | import { BucketPolicy } from '../entities/storage-bucket'
4 |
5 | export class CreateBucketDto {
6 | @ApiProperty({
7 | description: 'The short name of the bucket which not contain the appid',
8 | })
9 | @IsNotEmpty()
10 | @Matches(/^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$/)
11 | shortName: string
12 |
13 | @ApiProperty({
14 | enum: BucketPolicy,
15 | })
16 | @IsEnum(BucketPolicy)
17 | @IsNotEmpty()
18 | policy: BucketPolicy
19 |
20 | fullname(appid: string) {
21 | return `${appid}-${this.shortName}`
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/services/runtime-exporter/src/logger.ts:
--------------------------------------------------------------------------------
1 | import { LoggerInterface } from 'database-proxy'
2 | import * as log4js from 'log4js'
3 | import Config from './config'
4 |
5 | /**
6 | * Create logger instance
7 | * @param category log category
8 | * @param level the logger level : 'fatal', 'error', 'warning', 'info', 'debug', 'trace'
9 | * @returns
10 | */
11 | export function createLogger(
12 | category: string,
13 | level?: string,
14 | ): LoggerInterface {
15 | const logger = log4js.getLogger(category)
16 | logger.level = level ?? Config.LOG_LEVEL
17 |
18 | return logger as any
19 | }
20 |
21 | /**
22 | * The global logger instance
23 | */
24 | export const logger = createLogger('server')
25 |
--------------------------------------------------------------------------------
/web/src/apis/dependence.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | interface KeyWord {
3 | q: String;
4 | }
5 |
6 | export async function DependencySearch(params: KeyWord | any): Promise {
7 | if (params.q === "") {
8 | return Promise.resolve([]);
9 | } else {
10 | return axios.get(`https://registry.npmjs.org/-/v1/search`, {
11 | params: {
12 | text: params.q,
13 | size: 4,
14 | },
15 | });
16 | }
17 | }
18 |
19 | export async function GetDependencyVersions(params: KeyWord | any): Promise {
20 | if (params.q === "") {
21 | return Promise.resolve([]);
22 | } else {
23 | return axios.get(`https://registry.npmjs.org/${params.q}`);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/web/src/pages/homepage/circle.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | type Props = {};
4 |
5 | const circle = (props: Props) => {
6 | return (
7 |
13 | );
14 | };
15 |
16 | export default circle;
17 |
--------------------------------------------------------------------------------
/server/src/website/entities/website.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 | import { DomainPhase, DomainState } from 'src/gateway/entities/runtime-domain'
3 | import { StorageBucket } from 'src/storage/entities/storage-bucket'
4 |
5 | export class WebsiteHosting {
6 | _id?: ObjectId
7 | appid: string
8 | bucketName: string
9 | domain: string
10 | isCustom: boolean
11 | state: DomainState
12 | phase: DomainPhase
13 | createdAt: Date
14 | updatedAt: Date
15 | lockedAt: Date
16 |
17 | constructor(partial: Partial) {
18 | Object.assign(this, partial)
19 | }
20 | }
21 |
22 | export type WebsiteHostingWithBucket = WebsiteHosting & {
23 | bucket: StorageBucket
24 | }
25 |
--------------------------------------------------------------------------------
/server/src/authentication/dto/send-phone-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsEnum, IsNotEmpty, IsString, Matches } from 'class-validator'
3 | import { SmsVerifyCodeType } from '../entities/sms-verify-code'
4 |
5 | export class SendPhoneCodeDto {
6 | @ApiProperty({
7 | description: 'phone',
8 | example: '13805718888',
9 | })
10 | @IsString()
11 | @IsNotEmpty()
12 | @Matches(/^1[3-9]\d{9}$/)
13 | phone: string
14 |
15 | @ApiProperty({
16 | description: 'verify code type',
17 | example: 'Signin | Signup | ResetPassword | Bind | Unbind | ChangePhone',
18 | })
19 | @IsNotEmpty()
20 | @IsEnum(SmsVerifyCodeType)
21 | type: SmsVerifyCodeType
22 | }
23 |
--------------------------------------------------------------------------------
/server/src/group/entities/group-invite-code.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 | import { GroupRole } from './group-member'
4 |
5 | export class GroupInviteCode {
6 | @ApiProperty({ type: 'string' })
7 | _id?: ObjectId
8 |
9 | @ApiPropertyOptional({ type: 'string' })
10 | usedBy?: ObjectId
11 |
12 | @ApiProperty()
13 | code: string
14 |
15 | @ApiProperty()
16 | role: GroupRole
17 |
18 | @ApiProperty({ type: 'string' })
19 | groupId: ObjectId
20 |
21 | @ApiProperty({ type: 'string' })
22 | createdBy: ObjectId
23 |
24 | @ApiProperty()
25 | createdAt: Date
26 |
27 | @ApiProperty()
28 | updatedAt: Date
29 | }
30 |
--------------------------------------------------------------------------------
/server/src/user/entities/user.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 | import { UserProfile } from './user-profile'
4 |
5 | export class User {
6 | @ApiProperty({ type: String })
7 | _id?: ObjectId
8 |
9 | @ApiProperty()
10 | username: string
11 |
12 | @ApiPropertyOptional()
13 | email?: string
14 |
15 | @ApiPropertyOptional()
16 | phone?: string
17 |
18 | @ApiPropertyOptional()
19 | github?: number
20 |
21 | @ApiProperty()
22 | createdAt: Date
23 |
24 | @ApiProperty()
25 | updatedAt: Date
26 | }
27 |
28 | export class UserWithProfile extends User {
29 | @ApiPropertyOptional()
30 | profile?: UserProfile
31 | }
32 |
--------------------------------------------------------------------------------
/web/src/hooks/useCustomToast.ts:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useToast } from "@chakra-ui/react";
3 |
4 | function useCustomToast() {
5 | const toast = useToast();
6 |
7 | const showSuccess = (text: string | React.ReactNode) => {
8 | toast({
9 | position: "top",
10 | title: text,
11 | status: "success",
12 | duration: 1000,
13 | });
14 | };
15 |
16 | const showError = (text: string | React.ReactNode) => {
17 | toast({
18 | position: "top",
19 | title: text,
20 | status: "error",
21 | duration: 1000,
22 | });
23 | };
24 | return {
25 | showSuccess,
26 | showError,
27 | };
28 | }
29 |
30 | export default useCustomToast;
31 |
--------------------------------------------------------------------------------
/cli/src/command/application/index.ts:
--------------------------------------------------------------------------------
1 | import { Command, program } from 'commander'
2 | import { init, list } from '../../action/application'
3 |
4 | export function command(): Command {
5 | const cmd = program.command('app')
6 |
7 | cmd
8 | .command('init ')
9 | .description('initialize application')
10 | .option('-s, --sync', 'sync application data', false)
11 | .option('-b --basic-mode', 'only create .app.yaml, do not init whole project', false)
12 | .action((appid, options) => {
13 | init(appid, options)
14 | })
15 |
16 | cmd
17 | .command('list')
18 | .description('list application')
19 | .action(() => {
20 | list()
21 | })
22 |
23 | return cmd
24 | }
25 |
--------------------------------------------------------------------------------
/cli/src/command/environment/index.ts:
--------------------------------------------------------------------------------
1 | import { Command, program } from 'commander'
2 | import { checkApplication } from '../../common/hook'
3 | import { pull, push } from '../../action/environment'
4 |
5 | export function command(): Command {
6 | const cmd = program
7 | .command('environment')
8 | .alias('env')
9 | .hook('preAction', () => {
10 | checkApplication()
11 | })
12 |
13 | cmd
14 | .command('pull')
15 | .description('pull environment variables')
16 | .action(() => {
17 | pull()
18 | })
19 |
20 | cmd
21 | .command('push')
22 | .description('push environment variables')
23 | .action(() => {
24 | push()
25 | })
26 |
27 | return cmd
28 | }
29 |
--------------------------------------------------------------------------------
/web/src/pages/app/setting/SysSetting/AppEnvList/EditTextarea/index.tsx:
--------------------------------------------------------------------------------
1 | import { Textarea } from "@chakra-ui/react";
2 | import { t } from "i18next";
3 |
4 | const EditTextarea = function (props: {
5 | text: string;
6 | value: number;
7 | onChange: (data: any) => any;
8 | onBlur: (data: any) => any;
9 | disabled: boolean;
10 | }) {
11 | const { text, value, onBlur, onChange, disabled } = props;
12 | return (
13 |
22 | );
23 | };
24 |
25 | export default EditTextarea;
26 |
--------------------------------------------------------------------------------
/packages/database-ql/src/geo/interface.ts:
--------------------------------------------------------------------------------
1 | export interface ISerializedPoint {
2 | type: string
3 | coordinates: [number, number]
4 | }
5 |
6 | export interface ISerializedLineString {
7 | type: string
8 | coordinates: [number, number][]
9 | }
10 |
11 | export interface ISerializedPolygon {
12 | type: string
13 | coordinates: [number, number][][]
14 | }
15 |
16 | export interface ISerializedMultiPoint {
17 | type: string
18 | coordinates: [number, number][]
19 | }
20 |
21 | export interface ISerializedMultiLineString {
22 | type: string
23 | coordinates: [number, number][][]
24 | }
25 |
26 | export interface ISerializedMultiPolygon {
27 | type: string
28 | coordinates: [number, number][][][]
29 | }
30 |
--------------------------------------------------------------------------------
/server/src/utils/decorator.ts:
--------------------------------------------------------------------------------
1 | import { createParamDecorator, ExecutionContext } from '@nestjs/common'
2 |
3 | export const InjectUser = createParamDecorator(
4 | (data: unknown, ctx: ExecutionContext) => {
5 | const request = ctx.switchToHttp().getRequest()
6 | return request.user
7 | },
8 | )
9 |
10 | export const InjectGroup = createParamDecorator(
11 | (data: unknown, ctx: ExecutionContext) => {
12 | const request = ctx.switchToHttp().getRequest()
13 | return request.group
14 | },
15 | )
16 |
17 | export const InjectApplication = createParamDecorator(
18 | (data: unknown, ctx: ExecutionContext) => {
19 | const request = ctx.switchToHttp().getRequest()
20 | return request.application
21 | },
22 | )
23 |
--------------------------------------------------------------------------------
/packages/database-proxy/docs/rules-v2.json:
--------------------------------------------------------------------------------
1 | {
2 | "categories": {
3 | "read": true,
4 | "update": "$role === 'admin'",
5 | "add": "$role === 'admin'",
6 | "remove": "$role === 'admin'",
7 | "count": true,
8 | "watch": true,
9 | "$schema": {
10 | "password": { "match": "^\\d{6,10}$"},
11 | "author_id": "$value == $userid",
12 | "type": {"required": true, "in": ["choice", "fill"]},
13 | "title": {"length": [4, 64], "required": true, "unique": true},
14 | "content": {"length": [4, 20480]},
15 | "total": {"number": [0, 100], "default": 0, "required": true}
16 | },
17 | "$version": 2
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/server/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing'
2 | import { INestApplication } from '@nestjs/common'
3 | import * as request from 'supertest'
4 | import { AppModule } from './../src/app.module'
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile()
13 |
14 | app = moduleFixture.createNestApplication()
15 | await app.init()
16 | })
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!')
23 | })
24 | })
25 |
--------------------------------------------------------------------------------
/server/src/user/user.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { UserService } from './user.service'
3 | import { PatService } from './pat.service'
4 | import { PatController } from './pat.controller'
5 | import { UserController } from './user.controller'
6 | import { QuotaService } from './quota.service'
7 | import { ApplicationService } from 'src/application/application.service'
8 | import { SettingService } from 'src/setting/setting.service'
9 |
10 | @Module({
11 | providers: [
12 | UserService,
13 | PatService,
14 | QuotaService,
15 | ApplicationService,
16 | SettingService,
17 | ],
18 | exports: [UserService],
19 | controllers: [PatController, UserController],
20 | })
21 | export class UserModule {}
22 |
--------------------------------------------------------------------------------
/web/src/components/TextButton/index.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef } from "react";
2 | import { Button } from "@chakra-ui/react";
3 | import clsx from "clsx";
4 | const TextButton = function (
5 | props: {
6 | text: string;
7 | onClick?: () => void;
8 | className?: string;
9 | type?: "submit" | undefined;
10 | },
11 | ref: any,
12 | ) {
13 | const { text, type, onClick, className } = props;
14 | return (
15 |
26 | );
27 | };
28 | export default forwardRef(TextButton);
29 |
--------------------------------------------------------------------------------
/web/src/pages/app/mods/SideBar/index.module.scss:
--------------------------------------------------------------------------------
1 | .icon {
2 | color: #888d97;
3 | cursor: pointer;
4 | border-radius: 4px;
5 | height: 52px;
6 | width: 42px;
7 | display: flex;
8 | flex-direction: column;
9 | justify-content: center;
10 | font-weight: 500;
11 |
12 | svg {
13 | fill: #9ca2a8;
14 | }
15 | }
16 |
17 | .icon:hover,
18 | .icon.current {
19 | background-color: var(--chakra-colors-primary-200);
20 | color: var(--chakra-colors-primary-700);
21 |
22 | svg {
23 | fill: var(--chakra-colors-primary-600);
24 | }
25 | }
26 |
27 | [data-theme="dark"] .icon:hover,
28 | [data-theme="dark"] .icon.current {
29 | background: none;
30 |
31 | svg {
32 | fill: var(--chakra-colors-primary-600);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/web/src/pages/homepage/contact.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTranslation } from "react-i18next";
3 |
4 | import useSiteSettingStore from "../siteSetting";
5 |
6 | type Props = {};
7 |
8 | const Contact = (props: Props) => {
9 | const { t } = useTranslation();
10 | const { siteSettings } = useSiteSettingStore();
11 | return (
12 |
22 | );
23 | };
24 |
25 | export default Contact;
26 |
--------------------------------------------------------------------------------
/.github/no-response.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-no-response - https://github.com/probot/no-response
2 |
3 | # Number of days of inactivity before an Issue is closed for lack of response
4 | daysUntilClose: 7
5 | # Label requiring a response
6 | responseRequiredLabel: waiting-for-info
7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable
8 | closeComment: >
9 | This issue has been automatically closed because there has been no response
10 | to our request for more information from the original author. With only the
11 | information that is currently in the issue, we don't have enough information
12 | to take action. Please reach out if you have or find the answers we need so
13 | that we can investigate further.
14 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Number of days of inactivity before an issue becomes stale
4 | daysUntilStale: 15
5 | # Number of days of inactivity before a stale issue is closed
6 | daysUntilClose: 3
7 | # Issues with these labels will never be considered stale
8 | exemptLabels:
9 | - do-not-close
10 | # Label to use when marking an issue as stale
11 | staleLabel: stale
12 | # Comment to post when marking an issue as stale. Set to `false` to disable
13 | markComment: >
14 | This issue has been automatically marked as stale because it has not had
15 | recent activity. It will be closed if no further activity occurs. Thank you
16 | for your contributions.
17 | # Comment to post when closing a stale issue. Set to `false` to disable
18 | closeComment: true
19 |
--------------------------------------------------------------------------------
/server/src/region/region.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get, Logger } from '@nestjs/common'
2 | import { ApiOperation, ApiTags } from '@nestjs/swagger'
3 | import { ResponseUtil } from '../utils/response'
4 | import { RegionService } from './region.service'
5 |
6 | @ApiTags('Public')
7 | @Controller('regions')
8 | export class RegionController {
9 | private readonly logger = new Logger(RegionController.name)
10 | constructor(private readonly regionService: RegionService) {}
11 |
12 | /**
13 | * Get region list
14 | * @returns
15 | */
16 | @ApiOperation({ summary: 'Get region list' })
17 | @Get()
18 | async getRegions() {
19 | const data = await this.regionService.findAllDesensitized()
20 | return ResponseUtil.ok(data)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/web/src/pages/app/database/BottomPanel/index.tsx:
--------------------------------------------------------------------------------
1 | import { Button, HStack } from "@chakra-ui/react";
2 | import { t } from "i18next";
3 |
4 | import Panel from "@/components/Panel";
5 |
6 | import useCustomSettingStore from "@/pages/customSetting";
7 |
8 | function BottomPanel() {
9 | const store = useCustomSettingStore();
10 |
11 | return (
12 |
13 |
14 |
21 |
22 |
23 | );
24 | }
25 |
26 | export default BottomPanel;
27 |
--------------------------------------------------------------------------------
/runtimes/nodejs/src/support/database-change-stream/website-hosting-change-stream.ts:
--------------------------------------------------------------------------------
1 | import { DatabaseChangeStream } from '.'
2 | import { WEBSITE_HOSTING_COLLECTION } from '../../constants'
3 | import { DatabaseAgent } from '../../db'
4 |
5 | export class WebsiteHostingChangeStream {
6 | static websiteHosting = []
7 |
8 | static initialize() {
9 | this.onStreamChange()
10 |
11 | DatabaseChangeStream.onStreamChange(
12 | WEBSITE_HOSTING_COLLECTION,
13 | this.onStreamChange.bind(this),
14 | )
15 | }
16 |
17 | static async onStreamChange() {
18 | const websiteHosting = await DatabaseAgent.db
19 | .collection(WEBSITE_HOSTING_COLLECTION)
20 | .find()
21 | .toArray()
22 | this.websiteHosting = websiteHosting
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/docs/zh/cloud-database/database-ql/del.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 删除数据
3 | ---
4 |
5 | # 删除数据
6 |
7 | Laf 云数据库删除数据,包括删除文档和删除集合。同时支持单个删除和批量删除。
8 |
9 | ## 通过指定条件删除单个文档
10 |
11 | 我们可以配合 `where` 以及各种高级指令来使用 `remove`。
12 |
13 | ```js
14 | // 删除 user 集合中,name 为 jack 的一条记录
15 | const res = await db.collection('user').where({ name: "jack" }).remove()
16 | console.log(res)
17 | ```
18 |
19 | ## 通过指定条件批量删除文档
20 |
21 | 上面示例执行一次只能删除一条数据,如果想要批量删除要在 `remove()` 中添加 `{multi: true}`
22 |
23 | ```js
24 | // 删除 user 表中所有 name 为 jack 的记录
25 | await db.collection('user')
26 | .where({ name: "jack" })
27 | .remove({ multi: true })
28 | ```
29 |
30 | ## 清空集合(危险操作)
31 |
32 | 如果我们想删除一个集合中的所有数据,可以这样操作。
33 |
34 | ```js
35 | // 清空 user 集合
36 | await db.collection('user').remove({ multi: true })
37 | ```
38 |
--------------------------------------------------------------------------------
/web/src/components/SectionList/index.module.scss:
--------------------------------------------------------------------------------
1 | .sectionList {
2 | overflow-y: hidden;
3 | overflow-x: hidden;
4 | height: 100%;
5 |
6 | li {
7 | cursor: pointer;
8 | display: flex;
9 | min-height: 24px;
10 | align-items: center;
11 | justify-content: space-between;
12 | padding: 0px 4px 0px 12px;
13 | margin-bottom: 2px;
14 |
15 | span {
16 | vertical-align: middle;
17 | }
18 |
19 | svg {
20 | fill: #7b838b;
21 | }
22 |
23 | &.small {
24 | height: 32px;
25 | }
26 |
27 | &:hover,
28 | &.active {
29 | background-color: #00b3b01a;
30 | color: var(--chakra-colors-primary-600);
31 |
32 | svg {
33 | fill: var(--chakra-colors-primary-600);
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/runtimes/nodejs/src/support/init-hook.ts:
--------------------------------------------------------------------------------
1 | import { INIT_FUNCTION_NAME } from '../constants'
2 | import { FunctionCache, FunctionExecutor } from './engine'
3 | import { logger } from './logger'
4 |
5 | /**
6 | * Init hook for `__init__` cloud function
7 | */
8 | export class InitHook {
9 | static async invoke() {
10 | const func = FunctionCache.get(INIT_FUNCTION_NAME)
11 | if (!func) {
12 | return
13 | }
14 | const executor = new FunctionExecutor(func)
15 | const result = await executor.invoke(
16 | {
17 | method: 'INIT',
18 | __function_name: func.name,
19 | },
20 | false,
21 | )
22 |
23 | if (result.error) {
24 | return logger.error(result.error)
25 | }
26 |
27 | logger.info('__init__ hook invoked')
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.github/actions/build-docs/action.yml:
--------------------------------------------------------------------------------
1 | name: Build Laf Docs
2 | description: Build Laf Docs, to reuse in other workflows
3 |
4 | inputs:
5 | docs-path:
6 | description: 'Path to docs folder'
7 | required: false
8 | default: 'docs'
9 |
10 |
11 | # development docs: https://docs.github.com/en/actions/creating-actions/creating-a-composite-action
12 |
13 | runs:
14 | using: composite
15 | steps:
16 | - name: Set Node.js 18.x
17 | uses: actions/setup-node@v3
18 | with:
19 | node-version: 18.x
20 | - name: Run Install
21 | working-directory: ${{ inputs.docs-path }}
22 | run: npm install
23 | shell: bash
24 | - name: Run Build
25 | working-directory: ${{ inputs.docs-path }}
26 | run: npm run build
27 | shell: bash
28 |
--------------------------------------------------------------------------------
/server/src/storage/entities/storage-user.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 |
3 | export enum StoragePhase {
4 | Creating = 'Creating',
5 | Created = 'Created',
6 | Deleting = 'Deleting',
7 | Deleted = 'Deleted',
8 | }
9 |
10 | export enum StorageState {
11 | Active = 'Active',
12 | Inactive = 'Inactive',
13 | Deleted = 'Deleted',
14 | }
15 |
16 | export class StorageUser {
17 | _id?: ObjectId
18 | appid: string
19 | accessKey: string
20 | secretKey: string
21 | state: StorageState
22 | phase: StoragePhase
23 | dataSize: number
24 | lockedAt: Date
25 | usageCaptureLockedAt: Date
26 | usageLimitLockedAt: Date
27 | createdAt: Date
28 | updatedAt: Date
29 |
30 | constructor(partial: Partial) {
31 | Object.assign(this, partial)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/web/src/components/Panel/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { Box, useColorModeValue } from "@chakra-ui/react";
3 | import clsx from "clsx";
4 |
5 | import PanelHeader from "./Header";
6 |
7 | const Panel = (props: {
8 | className?: string;
9 | style?: React.CSSProperties;
10 | children: React.ReactNode;
11 | onClick?: () => void;
12 | }) => {
13 | const { className, style = {}, onClick } = props;
14 | const bg = useColorModeValue("lafWhite.200", "lafDark.200");
15 | return (
16 |
22 | {props.children}
23 |
24 | );
25 | };
26 |
27 | Panel.Header = PanelHeader;
28 |
29 | export default Panel;
30 |
--------------------------------------------------------------------------------
/packages/database-proxy/src/validators/lookup/index.ts:
--------------------------------------------------------------------------------
1 | import { Handler } from '../../processor'
2 | import { ActionType } from '../../types'
3 |
4 | /**
5 | * 此验证器是缺省验证器,不可配置:
6 | * - 检查 aggregate 操作中是否包含 $lookup,并禁止客户端进行 $lookup 操作
7 | *
8 | * @TODO 未来可考虑支持 $lookup 的子查询权限验证,相对复杂,暂不考虑
9 | *
10 | * @param config
11 | * @param context
12 | */
13 |
14 | export const LookupHandler: Handler = async function (_config, context) {
15 | const { action } = context.params
16 | if (action !== ActionType.AGGREGATE) {
17 | return null
18 | }
19 |
20 | const stages = context.params?.stages || []
21 | const [foundLookup] = stages.filter((item) => item.stageKey === '$lookup')
22 |
23 | if (foundLookup) {
24 | return '$lookup operation is forbidden for client'
25 | }
26 |
27 | return null
28 | }
29 |
--------------------------------------------------------------------------------
/server/src/function-template/function-template.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { FunctionTemplateService } from './function-template.service'
3 | import { FunctionTemplateController } from './function-template.controller'
4 | import { ApplicationModule } from 'src/application/application.module'
5 | import { DatabaseModule } from 'src/database/database.module'
6 | import { FunctionModule } from 'src/function/function.module'
7 | import { DependencyModule } from '../dependency/dependency.module'
8 |
9 | @Module({
10 | imports: [
11 | ApplicationModule,
12 | DatabaseModule,
13 | FunctionModule,
14 | DependencyModule,
15 | ],
16 | controllers: [FunctionTemplateController],
17 | providers: [FunctionTemplateService],
18 | })
19 | export class FunctionTemplateModule {}
20 |
--------------------------------------------------------------------------------
/server/src/storage/entities/storage-bucket.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 | import { StoragePhase, StorageState } from './storage-user'
3 | import { WebsiteHosting } from 'src/website/entities/website'
4 | import { BucketDomain } from 'src/gateway/entities/bucket-domain'
5 |
6 | export enum BucketPolicy {
7 | readwrite = 'readwrite',
8 | readonly = 'readonly',
9 | private = 'private',
10 | }
11 |
12 | export class StorageBucket {
13 | _id?: ObjectId
14 | appid: string
15 | name: string
16 | shortName: string
17 | policy: BucketPolicy
18 | state: StorageState
19 | phase: StoragePhase
20 | lockedAt: Date
21 | createdAt: Date
22 | updatedAt: Date
23 | }
24 |
25 | export type StorageWithRelations = StorageBucket & {
26 | domain: BucketDomain
27 | websiteHosting: WebsiteHosting
28 | }
29 |
--------------------------------------------------------------------------------
/web/src/pages/homepage/status.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useTranslation } from "react-i18next";
3 |
4 | import useSiteSettingStore from "../siteSetting";
5 |
6 | import styles from "./status.module.scss";
7 |
8 | export default function Status() {
9 | const { t } = useTranslation();
10 | const { siteSettings } = useSiteSettingStore();
11 | return (
12 |
18 | {t("ServerStatus")}
19 | {Array.from({ length: 8 }).map((item, index) => {
20 | return ;
21 | })}
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/.github/gh-bot.yml:
--------------------------------------------------------------------------------
1 | version: v1
2 | debug: true
3 | action:
4 | printConfig: false
5 | release:
6 | retry: 15s
7 | actionName: Release
8 | allowOps:
9 | - maslow
10 | bot:
11 | prefix: /
12 | spe: _
13 | allowOps:
14 | - sealos-ci-robot
15 | - sealos-release-robot
16 | email: sealos-ci-robot@sealos.io
17 | username: sealos-ci-robot
18 | repo:
19 | org: false
20 |
21 | message:
22 | success: |
23 | 🤖 says: Hooray! The action {{.Body}} has been completed successfully. 🎉
24 | format_error: |
25 | 🤖 says: ‼️ There is a formatting issue with the action, kindly verify the action's format.
26 | permission_error: |
27 | 🤖 says: ‼️ The action doesn't have permission to trigger.
28 | release_error: |
29 | 🤖 says: ‼️ Release action failed.
30 | Error details: {{.Error}}
31 |
--------------------------------------------------------------------------------
/server/src/account/entities/payment-channel.ts:
--------------------------------------------------------------------------------
1 | import { ObjectId } from 'mongodb'
2 | import { PaymentChannelType } from './account-charge-order'
3 | import { BaseState } from './account'
4 | import { ApiProperty } from '@nestjs/swagger'
5 |
6 | export class PaymentChannel {
7 | @ApiProperty({ type: String })
8 | _id?: ObjectId
9 |
10 | @ApiProperty({ enum: PaymentChannelType, type: String })
11 | type: PaymentChannelType
12 |
13 | @ApiProperty()
14 | name: string
15 |
16 | @ApiProperty()
17 | spec: S
18 |
19 | @ApiProperty({ type: String, enum: BaseState })
20 | state: BaseState
21 |
22 | @ApiProperty()
23 | createdAt: Date
24 |
25 | @ApiProperty()
26 | updatedAt: Date
27 |
28 | constructor(partial: Partial>) {
29 | Object.assign(this, partial)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/server/src/application/bundle.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, Logger } from '@nestjs/common'
2 | import { ApplicationBundle } from 'src/application/entities/application-bundle'
3 | import { SystemDatabase } from 'src/system-database'
4 |
5 | @Injectable()
6 | export class BundleService {
7 | private readonly logger = new Logger(BundleService.name)
8 | private readonly db = SystemDatabase.db
9 |
10 | async findOne(appid: string) {
11 | const bundle = await this.db
12 | .collection('ApplicationBundle')
13 | .findOne({ appid })
14 |
15 | return bundle
16 | }
17 |
18 | async deleteOne(appid: string) {
19 | const res = await this.db
20 | .collection('ApplicationBundle')
21 | .findOneAndDelete({ appid })
22 |
23 | return res.value
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/cli/src/action/environment/index.ts:
--------------------------------------------------------------------------------
1 | import { environmentVariableControllerGet, environmentVariableControllerUpdateAll } from '../../api/v1/application'
2 | import { AppSchema } from '../../schema/app'
3 | import { EnvironmentSchema } from '../../schema/environment'
4 | import { getEmoji } from '../../util/print'
5 |
6 | export async function pull(): Promise {
7 | const appSchema = AppSchema.read()
8 | const env = await environmentVariableControllerGet(appSchema.appid)
9 | EnvironmentSchema.write(env)
10 | console.log(`${getEmoji('✅')} env pulled`)
11 | }
12 |
13 | export async function push(): Promise {
14 | const appSchema = AppSchema.read()
15 | const env = EnvironmentSchema.read()
16 | await environmentVariableControllerUpdateAll(appSchema.appid, env)
17 | console.log(`${getEmoji('✅')} env pushed`)
18 | }
19 |
--------------------------------------------------------------------------------
/web/public/homepage/icon_03.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/e2e/jest-sequencer.js:
--------------------------------------------------------------------------------
1 | const TestSequencer = require('@jest/test-sequencer').default
2 | const path = require('path')
3 |
4 | class CustomSequencer extends TestSequencer {
5 | sort(tests) {
6 | const target_test_path = path.join(__dirname, 'target.test.js')
7 |
8 | const target_test_index = tests.findIndex(
9 | (t) => t.path === target_test_path
10 | )
11 |
12 | if (target_test_index == -1) {
13 | return tests
14 | }
15 |
16 | const target_test = tests[target_test_index]
17 |
18 | const ordered_tests = tests.slice()
19 |
20 | ordered_tests.splice(target_test_index, 1)
21 | ordered_tests.push(target_test) // adds to the tail
22 | // ordered_tests.unshift(target_test); // adds to the head
23 |
24 | return ordered_tests
25 | }
26 | }
27 |
28 | module.exports = CustomSequencer
29 |
--------------------------------------------------------------------------------
/server/src/account/entities/account-transaction.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class AccountTransaction {
5 | @ApiProperty({ type: String })
6 | _id?: ObjectId
7 |
8 | @ApiProperty({ type: String })
9 | accountId: ObjectId
10 |
11 | @ApiProperty()
12 | amount: number
13 |
14 | @ApiProperty()
15 | balance: number
16 |
17 | @ApiProperty()
18 | reward?: number
19 |
20 | @ApiProperty()
21 | message: string
22 |
23 | @ApiPropertyOptional({ type: String })
24 | orderId?: ObjectId
25 |
26 | @ApiPropertyOptional({ type: String })
27 | billingId?: ObjectId
28 |
29 | @ApiProperty()
30 | createdAt: Date
31 |
32 | constructor(partial: Partial) {
33 | Object.assign(this, partial)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/server/src/database/listeners/application.listener.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common'
2 | import { OnEvent } from '@nestjs/event-emitter'
3 | import { DedicatedDatabaseService } from '../dedicated-database/dedicated-database.service'
4 | import { ApplicationCreatingEvent } from 'src/application/events/application-creating.event'
5 |
6 | @Injectable()
7 | export class ApplicationListener {
8 | constructor(
9 | private readonly dedicatedDatabaseService: DedicatedDatabaseService,
10 | ) {}
11 |
12 | @OnEvent(ApplicationCreatingEvent.eventName, {
13 | promisify: true,
14 | async: true,
15 | })
16 | handleApplicationCreatedEvent(event: ApplicationCreatingEvent) {
17 | if (event.dto.dedicatedDatabase) {
18 | return this.dedicatedDatabaseService.create(event.appid, event.session)
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/web/public/homepage/icon_05.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/packages/client-sdk/tests/http/add_test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert')
2 | const client = require('../../dist/commonjs/index')
3 | const config = require('./config')
4 |
5 | describe('client-sdk(http): db.add()', function () {
6 | it('add one should be ok', async () => {
7 | const cloud = client.init({
8 | dbProxyUrl: config.dbProxyUrl,
9 | getAccessToken: config.getAccessToken,
10 | })
11 |
12 | const result = await cloud.database().collection('categories').add({
13 | title: 'title-add-2',
14 | content: 'content-add-2',
15 | })
16 |
17 | console.log({ result })
18 | const { data } = await cloud
19 | .database()
20 | .collection('categories')
21 | .doc(result.id)
22 | .get()
23 |
24 | assert.ok(result.id)
25 | assert.equal(data._id, result.id)
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/server/src/notification/entities/notification.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 | import { NotificationType } from '../notification-type'
4 |
5 | export enum NotificationState {
6 | Pending = 'Pending',
7 | Done = 'Done',
8 | }
9 |
10 | export class Notification {
11 | @ApiProperty({ type: String })
12 | _id?: ObjectId
13 |
14 | @ApiProperty({ enum: NotificationType })
15 | type: NotificationType
16 |
17 | @ApiProperty()
18 | title: string
19 |
20 | @ApiProperty()
21 | content: string
22 |
23 | @ApiProperty({ enum: NotificationState })
24 | state: NotificationState
25 |
26 | @ApiProperty({ type: String })
27 | target: ObjectId
28 |
29 | lockedAt: Date
30 |
31 | @ApiProperty()
32 | createdAt: Date
33 |
34 | @ApiProperty()
35 | updatedAt: Date
36 | }
37 |
--------------------------------------------------------------------------------
/docs/zh/cloud-storage/website-hosting.md:
--------------------------------------------------------------------------------
1 |
2 | # 网站托管
3 |
4 | 在 laf 云存储中,可以选择一个存储桶开启网站托管服务。
5 |
6 | 网站托管会为你的网站自动提供一个独立的域名,也可以绑定自定义域名。
7 |
8 | 在存储桶中上传一个 `index.html` 的文件,作为默认首页。
9 |
10 |
11 | ## 开启网站托管
12 |
13 | 1. 创建一个存储桶,并设置其权限策略为 `readonly`,只有此权限的存储桶才能开启网站托管。
14 | 2. 将你的网站文件上传到该存储桶即可。
15 | 3. 在 `laf 控制台` 云存储页面,点击右上角「开启网站托管」,即可通过生成的地址访问你的网站。
16 |
17 | 
18 |
19 |
20 | ## 绑定自定义域名
21 |
22 | 网站托管支持绑定自己的域名,并会自动为其生成 HTTPS 证书,支持 `https` 和 `http` 访问。
23 |
24 | 按页面上操作提示,完成域名的 `CNAME` 解析,等待解析生效后,可继续绑定操作。
25 |
26 | 
27 |
28 | ::: tip 提示
29 | - 域名解析生效时间:1~10分钟不等,待解析生效后才可继续绑定操作。
30 | - 绑定自己的域名后,laf 将会自动为您的域名配置 `SSL` 证书,这个过程可能会有 1~2 分钟,之后即可通过 `https` 进行访问
31 | :::
32 |
33 |
34 |
35 | ## 更多
36 |
37 | [用 GitHub Action 自动构建前端并发布到网站托管](/zh/examples/website-hosting-ci-cd.md)
--------------------------------------------------------------------------------
/server/src/application/entities/runtime.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export class RuntimeImageGroup {
5 | @ApiProperty()
6 | main: string
7 |
8 | @ApiProperty()
9 | init: string
10 |
11 | @ApiPropertyOptional()
12 | sidecar?: string
13 | }
14 |
15 | export class Runtime {
16 | @ApiProperty({ type: String })
17 | _id?: ObjectId
18 |
19 | @ApiProperty()
20 | name: string
21 |
22 | @ApiProperty()
23 | type: string
24 |
25 | @ApiProperty()
26 | image: RuntimeImageGroup
27 |
28 | @ApiProperty()
29 | state: 'Active' | 'Inactive'
30 |
31 | @ApiProperty()
32 | version: string
33 |
34 | @ApiProperty()
35 | latest: boolean
36 |
37 | constructor(partial: Partial) {
38 | Object.assign(this, partial)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/node-modules-utils/tests/import.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert')
2 | const path = require('path')
3 | const { ImportParser, PackageDeclaration } = require('../dist')
4 |
5 | const nmp = path.resolve(__dirname, '../../app-service/node_modules')
6 |
7 | describe('npm-util(unit): Import Parser', () => {
8 | it('parse database-proxy index.d.ts', async () => {
9 | const pkg = new PackageDeclaration('database-proxy', nmp)
10 | await pkg.load()
11 | const dec0 = pkg.declarations[0]
12 | // console.log(dec0.packageName, dec0.path)
13 |
14 | const parser = new ImportParser()
15 | const r = parser.parseDependencies(dec0.content, dec0.path)
16 |
17 | // console.log(r)
18 | assert.ok(r.length > 0)
19 | assert.strictEqual(pkg.name, 'database-proxy')
20 | assert.ok(pkg.declarations.length > 0)
21 | })
22 | })
23 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [maslow] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/packages/client-sdk/tests/units/cloud_test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert')
2 | const client = require('../../dist/commonjs/index')
3 | const Db = client.Db
4 |
5 | function getAccessToken() {
6 | return 'test-token-xxx'
7 | }
8 |
9 | describe('client-sdk(unit): Cloud', function () {
10 | const config = {
11 | dbProxyUrl: 'http://localhost:8080/entry',
12 | getAccessToken,
13 | }
14 |
15 | it('init() should be ok', () => {
16 | const cloud = client.init(config)
17 |
18 | assert.ok(cloud instanceof client.Cloud)
19 | assert.equal(cloud.config.dbProxyUrl, config.dbProxyUrl)
20 | assert.equal(cloud.config.getAccessToken, getAccessToken)
21 | })
22 |
23 | it('database() should be ok', () => {
24 | const cloud = client.init(config)
25 | const db = cloud.database()
26 |
27 | assert.ok(db instanceof Db)
28 | })
29 | })
30 |
--------------------------------------------------------------------------------
/web/src/components/FileUpload/index.module.scss:
--------------------------------------------------------------------------------
1 | .formFileUpload {
2 | height: 16rem;
3 | width: 29rem;
4 | max-width: 100%;
5 | text-align: center;
6 | position: relative;
7 | }
8 |
9 | .inputFileUpload {
10 | display: none;
11 | }
12 |
13 | .labelFileUpload {
14 | height: 100%;
15 | display: flex;
16 | align-items: center;
17 | justify-content: center;
18 | border-width: 2px;
19 | border-radius: 1rem;
20 | border-style: dashed;
21 | }
22 |
23 | .uploadButton {
24 | cursor: pointer;
25 | padding: 0.25rem;
26 | font-size: 1rem;
27 | border: none;
28 | }
29 |
30 | .uploadButton:hover {
31 | text-decoration-line: underline;
32 | }
33 |
34 | .dragFileElement {
35 | position: absolute;
36 | width: 100%;
37 | height: 100%;
38 | border-radius: 1rem;
39 | top: 0px;
40 | right: 0px;
41 | bottom: 0px;
42 | left: 0px;
43 | }
44 |
--------------------------------------------------------------------------------
/server/src/account/entities/account.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export enum BaseState {
5 | Active = 'Active',
6 | Inactive = 'Inactive',
7 | }
8 |
9 | export class Account {
10 | @ApiProperty({ type: String })
11 | _id?: ObjectId
12 |
13 | @ApiProperty({
14 | type: Date,
15 | required: false,
16 | description: 'The timestamp when the account became owed',
17 | })
18 | owedAt?: Date
19 |
20 | @ApiProperty()
21 | balance: number
22 |
23 | @ApiProperty({ enum: BaseState })
24 | state: BaseState
25 |
26 | @ApiProperty()
27 | createdAt: Date
28 |
29 | @ApiProperty()
30 | updatedAt: Date
31 |
32 | @ApiProperty({ type: String })
33 | createdBy: ObjectId
34 |
35 | constructor(partial: Partial) {
36 | Object.assign(this, partial)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/server/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get, Logger } from '@nestjs/common'
2 | import { ApiOperation, ApiTags } from '@nestjs/swagger'
3 | import { ApiResponseArray, ResponseUtil } from './utils/response'
4 | import { SystemDatabase } from './system-database'
5 | import { Runtime } from './application/entities/runtime'
6 |
7 | @ApiTags('Public')
8 | @Controller()
9 | export class AppController {
10 | private readonly logger = new Logger(AppController.name)
11 | private readonly db = SystemDatabase.db
12 |
13 | /**
14 | * Get runtime list
15 | * @returns
16 | */
17 | @ApiOperation({ summary: 'Get application runtime list' })
18 | @ApiResponseArray(Runtime)
19 | @Get('runtimes')
20 | async getRuntimes() {
21 | const data = await this.db.collection('Runtime').find({}).toArray()
22 | return ResponseUtil.ok(data)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/web/src/components/ColorModeSwitch/index.tsx:
--------------------------------------------------------------------------------
1 | import { MoonIcon, SunIcon } from "@chakra-ui/icons";
2 | import { useColorMode } from "@chakra-ui/react";
3 | import clsx from "clsx";
4 |
5 | import { COLOR_MODE } from "@/constants";
6 |
7 | export default function ColorModeSwitch(props: { className?: string; fontSize?: number }) {
8 | const { toggleColorMode } = useColorMode();
9 | const { className, fontSize = 18 } = props;
10 | const darkMode = useColorMode().colorMode === COLOR_MODE.dark;
11 |
12 | return (
13 | {
16 | toggleColorMode();
17 | window.dispatchEvent(new Event("ColorModeChange"));
18 | }}
19 | >
20 | {darkMode ? : }
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/packages/database-ql/tests/units/get/page.test.js:
--------------------------------------------------------------------------------
1 | const { getDb } = require('../_utils')
2 | const assert = require('assert')
3 |
4 | describe('db-ql(unit): db::page()', () => {
5 | it('page() should be ok', async () => {
6 | const { db, req } = getDb()
7 | const res = await db.collection('tasks').page().get()
8 |
9 | // console.log(req.params)
10 | assert.equal(req.params.limit, 10)
11 | assert.equal(req.params.count, true)
12 | })
13 |
14 | it('page({ current: 2, size: 10}) should be ok', async () => {
15 | const { db, req } = getDb()
16 | const res = await db
17 | .collection('tasks')
18 | .page({ current: 3, size: 20 })
19 | .get()
20 |
21 | // console.log(req.params)
22 | assert.equal(req.params.offset, 40)
23 | assert.equal(req.params.limit, 20)
24 | assert.equal(req.params.count, true)
25 | })
26 | })
27 |
--------------------------------------------------------------------------------
/server/src/user/entities/user-profile.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 | class IdVerified {
4 | @ApiProperty({ type: Boolean })
5 | isVerified: boolean
6 |
7 | @ApiProperty({ type: Number })
8 | idVerifyFailedTimes: number
9 | }
10 |
11 | export class UserProfile {
12 | @ApiProperty({ type: String })
13 | _id?: ObjectId
14 |
15 | @ApiProperty({ type: String })
16 | uid: ObjectId
17 |
18 | @ApiPropertyOptional()
19 | openData?: any
20 |
21 | @ApiPropertyOptional()
22 | avatar?: string
23 |
24 | @ApiPropertyOptional()
25 | name?: string
26 |
27 | @ApiProperty({ type: IdVerified })
28 | idVerified?: IdVerified
29 |
30 | @ApiProperty()
31 | idCard?: string
32 |
33 | @ApiProperty()
34 | createdAt: Date
35 |
36 | @ApiProperty()
37 | updatedAt: Date
38 | }
39 |
--------------------------------------------------------------------------------
/.github/workflows/build-scripts-updated.yml:
--------------------------------------------------------------------------------
1 | name: build-scripts-updated
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches:
7 | - main
8 | paths:
9 | - "build/**"
10 | - "deploy/**"
11 | - ".github/workflows/build-scripts-updated.yml"
12 | - ".github/workflows/build-sealos-cluster-image.yml"
13 | - "!**/*.md"
14 |
15 | permissions:
16 | contents: read
17 |
18 | concurrency:
19 | group: build-scripts-updated-${{ github.ref }}
20 | cancel-in-progress: true
21 |
22 | jobs:
23 | notify:
24 | runs-on: ubuntu-latest
25 | steps:
26 | - name: Log workflow completion
27 | run: |
28 | echo "Build scripts updated workflow completed"
29 | echo "This will trigger build-sealos-cluster-image via workflow_run"
30 | echo "Ref: ${{ github.ref }}"
31 | echo "SHA: ${{ github.sha }}"
32 |
--------------------------------------------------------------------------------
/web/src/pages/home/service.ts:
--------------------------------------------------------------------------------
1 | import { useQuery } from "@tanstack/react-query";
2 |
3 | import { AccountControllerFindOne } from "@/apis/v1/accounts";
4 | import { ResourceControllerGetResourceBundles } from "@/apis/v1/resources";
5 |
6 | export const queryKeys = {
7 | useAccountQuery: ["useAccountQuery"],
8 | useBillingPriceQuery: ["useBillingPriceQuery"],
9 | useBillingResourceOptionsQuery: ["useBillingResourceOptionsQuery"],
10 | useResourceBundlesQuery: ["useBillingResourceBundlesQuery"],
11 | };
12 |
13 | export const useAccountQuery = () => {
14 | return useQuery(queryKeys.useAccountQuery, async () => {
15 | return AccountControllerFindOne({});
16 | });
17 | };
18 |
19 | export const useResourceBundlesQuery = () => {
20 | return useQuery(queryKeys.useResourceBundlesQuery, async () => {
21 | return ResourceControllerGetResourceBundles({});
22 | });
23 | };
24 |
--------------------------------------------------------------------------------
/server/src/generated/i18n.generated.ts:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT, file generated by nestjs-i18n */
2 |
3 | import { Path } from "nestjs-i18n";
4 | export type I18nTranslations = {
5 | "function": {
6 | "create": {
7 | "nameExist": string;
8 | "maxCount": string;
9 | "error": string;
10 | };
11 | "get": {};
12 | "update": {
13 | "error": string;
14 | };
15 | "delete": {
16 | "error": string;
17 | };
18 | "compile": {
19 | "codeRequired": string;
20 | };
21 | "common": {
22 | "notFound": string;
23 | };
24 | };
25 | "notification": {
26 | "InsufficientBalance": {
27 | "title": string;
28 | "content": string;
29 | };
30 | };
31 | };
32 | export type I18nPath = Path;
33 |
--------------------------------------------------------------------------------
/server/src/group/entities/group-member.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | export enum GroupRole {
5 | Owner = 'owner',
6 | Admin = 'admin',
7 | Developer = 'developer',
8 | }
9 |
10 | const roleLevel = {
11 | [GroupRole.Owner]: 0b100,
12 | [GroupRole.Admin]: 0b010,
13 | [GroupRole.Developer]: 0b001,
14 | } as const
15 |
16 | export const getRoleLevel = (role: GroupRole) => {
17 | return roleLevel[role]
18 | }
19 |
20 | export class GroupMember {
21 | @ApiProperty({ type: 'string' })
22 | _id?: ObjectId
23 |
24 | @ApiProperty({ type: 'string' })
25 | uid: ObjectId
26 |
27 | @ApiProperty({ type: 'string' })
28 | groupId: ObjectId
29 |
30 | @ApiProperty({ enum: GroupRole })
31 | role: GroupRole
32 |
33 | @ApiProperty()
34 | createdAt: Date
35 |
36 | @ApiProperty()
37 | updatedAt: Date
38 | }
39 |
--------------------------------------------------------------------------------
/web/src/pages/homepage/index.tsx:
--------------------------------------------------------------------------------
1 | import Ability from "./ability";
2 | import Choice from "./choice";
3 | import Contact from "./contact";
4 | import Footer from "./footer";
5 | import Hero from "./hero";
6 | import JoinUs from "./joinus";
7 | import Navbar from "./navbar";
8 |
9 | import "./homepage.css";
10 |
11 | import useInviteCode from "@/hooks/useInviteCode";
12 |
13 | export default function Home() {
14 | useInviteCode();
15 |
16 | return (
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/cli/src/common/hook.ts:
--------------------------------------------------------------------------------
1 | import { AppSchema } from '../schema/app'
2 |
3 | export function checkApplication() {
4 | if (!AppSchema.exist()) {
5 | console.error('Please run "laf app init" to initialize the application first')
6 | process.exit(1)
7 | }
8 | }
9 |
10 | export async function checkFunctionDebugToken() {
11 | const appSchema = AppSchema.read()
12 | const { developToken, developTokenExpire } = appSchema.function
13 | const timestamp = Date.parse(new Date().toString()) / 1000
14 | if (!developToken || developTokenExpire < timestamp) {
15 | await AppSchema.refresh()
16 | }
17 | }
18 |
19 | export async function checkStorageToken() {
20 | const appSchema = AppSchema.read()
21 | const { expire } = appSchema.storage
22 | const timestamp = Date.parse(new Date().toString()) / 1000
23 | if (expire < timestamp) {
24 | await AppSchema.refresh()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/web/public/homepage/cancel_btn.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/packages/database-proxy/src/dbi/request.ts:
--------------------------------------------------------------------------------
1 | import { Proxy } from '../proxy'
2 | import { RequestInterface } from 'database-ql'
3 | import { AccessorInterface } from '..'
4 | import { QueryParam, ResponseStruct } from 'database-ql/dist/commonjs/interface'
5 | import { ActionType } from 'database-ql/dist/commonjs/constant'
6 |
7 | export class Request implements RequestInterface {
8 | private accessor: AccessorInterface
9 |
10 | constructor(accessor: AccessorInterface) {
11 | this.accessor = accessor
12 | }
13 |
14 | async send(action: ActionType, data: QueryParam): Promise {
15 | const accessor = this.accessor
16 | const params = Proxy.parse(action as any, data)
17 | const ret = await accessor.execute(params)
18 |
19 | return {
20 | code: 0,
21 | data: ret,
22 | error: undefined,
23 | requestId: undefined,
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/web/public/js/monaco-editor.0.43.0/base/common/worker/simpleWorker.nls.js:
--------------------------------------------------------------------------------
1 | /*!-----------------------------------------------------------
2 | * Copyright (c) Microsoft Corporation. All rights reserved.
3 | * Version: 0.43.0(94c055bcbdd49f04a0fa15515e848542a79fb948)
4 | * Released under the MIT license
5 | * https://github.com/microsoft/vscode/blob/main/LICENSE.txt
6 | *-----------------------------------------------------------*/define("vs/base/common/worker/simpleWorker.nls",{"vs/base/common/platform":["_"],"vs/editor/common/languages":["array","boolean","class","constant","constructor","enumeration","enumeration member","event","field","file","function","interface","key","method","module","namespace","null","number","object","operator","package","property","string","struct","type parameter","variable","{0} ({1})"]});
7 |
8 | //# sourceMappingURL=../../../../../min-maps/vs/base/common/worker/simpleWorker.nls.js.map
--------------------------------------------------------------------------------
/runtimes/nodejs/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20.10.0
2 |
3 | RUN apt update && apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev git dumb-init -y
4 |
5 | # RUN npm install npm -g
6 |
7 | EXPOSE 8000
8 | EXPOSE 9000
9 |
10 | WORKDIR /app
11 | ENV LOG_LEVEL=debug
12 |
13 | # enable chalk colors
14 | ENV FORCE_COLOR=1
15 |
16 | COPY . /app
17 | # COPY --chown=node:node . /app
18 | RUN mkdir /app/data || true
19 | RUN mkdir /tmp/custom_dependency || true
20 | RUN chown node:node /app/data
21 | RUN chown node:node /app/functions
22 | RUN chown node:node /tmp/custom_dependency
23 | # RUN npm install
24 | # RUN npm run build
25 | RUN chown -R node:node /app/node_modules
26 | RUN chown node:node /app/package.json
27 | RUN chown node:node /app/package-lock.json
28 |
29 | USER node
30 |
31 | ENTRYPOINT ["/usr/bin/dumb-init", "--"]
32 |
33 | CMD [ "sh", "/app/start.sh" ]
34 |
--------------------------------------------------------------------------------
/server/src/user/entities/user-quota.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { ObjectId } from 'mongodb'
3 |
4 | type LimitOfDatabaseSyncCount = {
5 | countLimit: number
6 | timePeriodInSeconds: number
7 | }
8 |
9 | export class UserQuota {
10 | @ApiProperty({ type: String })
11 | _id?: ObjectId
12 |
13 | @ApiProperty({ type: String })
14 | uid: ObjectId
15 |
16 | @ApiProperty()
17 | limitOfCPU: number
18 |
19 | @ApiProperty()
20 | limitOfMemory: number
21 |
22 | @ApiProperty()
23 | limitCountOfApplication: number
24 |
25 | @ApiProperty({
26 | description: 'Limits of database synchronization count and time period.',
27 | type: { countLimit: Number, timePeriodInSeconds: Number },
28 | })
29 | limitOfDatabaseSyncCount: LimitOfDatabaseSyncCount
30 |
31 | @ApiProperty()
32 | createdAt: Date
33 |
34 | @ApiProperty()
35 | updatedAt: Date
36 | }
37 |
--------------------------------------------------------------------------------
/server/src/setting/setting.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, Logger } from '@nestjs/common'
2 | import { SystemDatabase } from 'src/system-database'
3 | import { Setting } from './entities/setting'
4 |
5 | @Injectable()
6 | export class SettingService {
7 | private readonly logger = new Logger(SettingService.name)
8 | private readonly db = SystemDatabase.db
9 |
10 | async findAllPublic() {
11 | return await this.db
12 | .collection('Setting')
13 | .find({ public: true })
14 | .toArray()
15 | }
16 |
17 | async findOnePublic(key: string) {
18 | return await this.db.collection('Setting').findOne({ key })
19 | }
20 |
21 | async findAll() {
22 | return await this.db.collection('Setting').find({}).toArray()
23 | }
24 |
25 | async findOne(key: string) {
26 | return await this.db.collection('Setting').findOne({ key })
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/client-sdk/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable indent */
2 | const path = require('path')
3 | const HtmlWebpackPlugin = require('html-webpack-plugin')
4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin')
5 |
6 | module.exports = {
7 | entry: {
8 | 'laf-client': './src/index-bundle.ts',
9 | },
10 | devtool: 'inline-source-map',
11 | target: 'web',
12 | module: {
13 | rules: [
14 | {
15 | test: /\.tsx?$/,
16 | use: 'ts-loader',
17 | exclude: /node_modules/,
18 | },
19 | ],
20 | },
21 | resolve: {
22 | extensions: ['.ts', '.js'],
23 | },
24 | plugins: [
25 | new CleanWebpackPlugin(),
26 | new HtmlWebpackPlugin({
27 | title: 'Output Management',
28 | }),
29 | ],
30 | output: {
31 | filename: '[name].bundle.js',
32 | path: path.resolve(__dirname, 'dist'),
33 | // libraryTarget: 'umd'
34 | },
35 | }
36 |
--------------------------------------------------------------------------------
/services/runtime-exporter/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": true,
3 | "compilerOptions": {
4 | "allowJs": false,
5 | "allowUnreachableCode": false,
6 | "allowUnusedLabels": false,
7 | "declaration": true,
8 | "module": "NodeNext",
9 | "target": "ES2022",
10 | "moduleResolution": "NodeNext",
11 | "esModuleInterop": true,
12 | "declarationMap": false,
13 | "noEmitOnError": true,
14 | "noFallthroughCasesInSwitch": true,
15 | "noImplicitAny": false,
16 | "noUnusedLocals": true,
17 | "noUnusedParameters": true,
18 | "outDir": "dist",
19 | "pretty": false,
20 | "removeComments": true,
21 | "sourceMap": true,
22 | "stripInternal": true,
23 | "skipDefaultLibCheck": true,
24 | "skipLibCheck": true,
25 | "alwaysStrict": true,
26 | "lib": [
27 | "ES2022"
28 | ]
29 | },
30 | "include": [
31 | "src/**/*",
32 | ],
33 | }
--------------------------------------------------------------------------------
/web/public/homepage/play.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/web/src/pages/app/setting/UserSetting/PATList/DateSelector/index.module.scss:
--------------------------------------------------------------------------------
1 | .customStyleDateSelector {
2 | :global {
3 | .react-datepicker__month-container {
4 | border: 1px solid #000;
5 | border-color: var(--chakra-colors-chakra-border-color);
6 | }
7 |
8 | .customStyle {
9 | .react-datepicker__day:hover {
10 | background-color: #e0f6f4;
11 | border-radius: 100%;
12 | }
13 |
14 | .react-datepicker__header {
15 | border: 0px;
16 | background-color: #fff;
17 | }
18 |
19 | .react-datepicker__day--selected,
20 | .react-datepicker__day--selected:hover,
21 | .react-datepicker__day--keyboard-selected,
22 | .react-datepicker__day--keyboard-selected:hover {
23 | background-color: var(--chakra-colors-primary-500);
24 | border-radius: 100%;
25 | color: #fff;
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/web/src/pages/home/mods/CreateAppModal/BundleItem/index.tsx:
--------------------------------------------------------------------------------
1 | // import { useColorMode } from "@chakra-ui/react";
2 | import clsx from "clsx";
3 |
4 | // import { COLOR_MODE } from "@/constants";
5 | import { TBundle } from "@/apis/typing";
6 |
7 | export default function BundleItem(props: {
8 | onChange: (...event: any[]) => void;
9 | bundle: TBundle | any;
10 | isActive: boolean;
11 | }) {
12 | const { bundle, isActive, onChange } = props;
13 | // const { colorMode } = useColorMode();
14 | // const darkMode = colorMode === COLOR_MODE.dark;
15 |
16 | return (
17 | onChange(bundle._id)}
19 | key={bundle._id}
20 | className={clsx("cursor-pointer rounded-md pl-4", {
21 | "text-[#219BF4]": isActive,
22 | })}
23 | >
24 |
25 |
{bundle.displayName}
26 |
27 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/server/src/application/dto/create-application.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsIn, IsNotEmpty, IsString, Length } from 'class-validator'
3 | import { ApplicationState } from '../entities/application'
4 | import { UpdateApplicationBundleDto } from './update-application.dto'
5 |
6 | const STATES = [ApplicationState.Running]
7 |
8 | export class CreateApplicationDto extends UpdateApplicationBundleDto {
9 | @ApiProperty()
10 | @IsString()
11 | @Length(1, 64)
12 | name: string
13 |
14 | @ApiProperty({
15 | default: ApplicationState.Running,
16 | enum: STATES,
17 | })
18 | @IsIn(STATES)
19 | state: ApplicationState
20 |
21 | @ApiProperty()
22 | @IsNotEmpty()
23 | @IsString()
24 | regionId: string
25 |
26 | @ApiProperty()
27 | @IsNotEmpty()
28 | @IsString()
29 | runtimeId: string
30 |
31 | validate() {
32 | return super.validate()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/services/runtime-exporter/tsconfig.dev.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": true,
3 | "compilerOptions": {
4 | "allowJs": false,
5 | "allowUnreachableCode": false,
6 | "allowUnusedLabels": false,
7 | "declaration": true,
8 | "module": "NodeNext",
9 | "target": "ES2022",
10 | "moduleResolution": "NodeNext",
11 | "esModuleInterop": true,
12 | "declarationMap": false,
13 | "noEmitOnError": true,
14 | "noFallthroughCasesInSwitch": true,
15 | "noImplicitAny": false,
16 | "noUnusedLocals": false,
17 | "noUnusedParameters": false,
18 | "outDir": "dist",
19 | "pretty": false,
20 | "removeComments": true,
21 | "sourceMap": true,
22 | "stripInternal": true,
23 | "skipDefaultLibCheck": true,
24 | "skipLibCheck": true,
25 | "alwaysStrict": true,
26 | "lib": [
27 | "ES2022"
28 | ]
29 | },
30 | "include": [
31 | "src/**/*",
32 | ],
33 | }
--------------------------------------------------------------------------------
/cli/src/command/database/index.ts:
--------------------------------------------------------------------------------
1 | import { Command, program } from 'commander'
2 | import { checkApplication } from '../../common/hook'
3 | import { exportDB, importDB } from '../../action/database'
4 |
5 | export function command(): Command {
6 | const cmd = program
7 | .command('database')
8 | .alias('db')
9 | .hook('preAction', () => {
10 | checkApplication()
11 | })
12 |
13 | cmd
14 | .command('export')
15 | .argument('[exportPath]', 'exportPath')
16 | .description('export database')
17 | .action((exportPath: string) => {
18 | exportDB(exportPath)
19 | })
20 |
21 | cmd
22 | .command('import')
23 | .argument('[sourceAppid]', 'sourceAppid')
24 | .argument('[importPath]', 'importPath')
25 | .description('import database')
26 | .action((sourceAppid, importPath: string) => {
27 | importDB(sourceAppid, importPath)
28 | })
29 |
30 | return cmd
31 | }
32 |
--------------------------------------------------------------------------------
/packages/eslint-config-laf/server.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | sourceType: 'module',
5 | },
6 | ignorePatterns: ['dist', 'i18n.generated.ts'],
7 | plugins: ['@typescript-eslint/eslint-plugin'],
8 | extends: [
9 | 'plugin:@typescript-eslint/recommended',
10 | 'plugin:prettier/recommended',
11 | ],
12 | env: {
13 | node: true,
14 | jest: true,
15 | },
16 | rules: {
17 | '@typescript-eslint/interface-name-prefix': 'off',
18 | '@typescript-eslint/explicit-function-return-type': 'off',
19 | '@typescript-eslint/explicit-module-boundary-types': 'off',
20 | '@typescript-eslint/no-explicit-any': 'off',
21 | 'no-console': 'warn',
22 | 'prettier/prettier': [
23 | 'error',
24 | {
25 | singleQuote: true,
26 | trailingComma: 'all',
27 | semi: false,
28 | },
29 | ],
30 | },
31 | }
32 |
--------------------------------------------------------------------------------
/server/src/function/function.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { JwtService } from '@nestjs/jwt'
3 | import { FunctionController } from './function.controller'
4 | import { FunctionService } from './function.service'
5 | import { DatabaseModule } from 'src/database/database.module'
6 | import { TriggerService } from 'src/trigger/trigger.service'
7 | import { FunctionRecycleBinService } from 'src/recycle-bin/cloud-function/function-recycle-bin.service'
8 | import { HttpModule } from '@nestjs/axios'
9 | import { ApplicationModule } from 'src/application/application.module'
10 |
11 | @Module({
12 | imports: [ApplicationModule, DatabaseModule, HttpModule],
13 | controllers: [FunctionController],
14 | providers: [
15 | FunctionService,
16 | FunctionRecycleBinService,
17 | JwtService,
18 | TriggerService,
19 | ],
20 | exports: [FunctionService],
21 | })
22 | export class FunctionModule {}
23 |
--------------------------------------------------------------------------------