├── .prettierignore
├── rundir
└── .gitkeep
├── backend
├── serialization
│ ├── .gitkeep
│ ├── vanilla_Microsoft-FSharp-Collections-FSharpMap-2-System-String-System-String-_baseline.json
│ ├── oplist-binary-latest.bin
│ ├── toplevels-binary-latest.bin
│ ├── vanilla_LibCloud-Queue-NotificationData_simple.json
│ ├── vanilla_System-Tuple-2-System-Guid-Microsoft-FSharp-Collections-FSharpList-1-System-UInt64-_simple.json
│ ├── vanilla_System-Tuple-5-System-String-System-String-System-String-NodaTime-Instant-System-Guid-_simple.json
│ └── vanilla_LibService-Rollbar-HoneycombJson_simple.json
├── src
│ ├── LibTreeSitter
│ │ ├── .gitignore
│ │ ├── paket.references
│ │ └── Helpers.fs
│ ├── DvalReprDeveloper
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── DvalReprDeveloper.fsproj
│ ├── ProdExec
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── ProdExec.fsproj
│ ├── QueueWorker
│ │ ├── paket.references
│ │ └── README.md
│ ├── BwdServer
│ │ ├── paket.references
│ │ └── README.md
│ ├── CronChecker
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── CronChecker.fsproj
│ ├── LibClientTypes
│ │ ├── paket.references
│ │ ├── ClientPusherTypes.fs
│ │ ├── README.md
│ │ └── LibClientTypes.fsproj
│ ├── LibHttpMiddleware
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── LibHttpMiddleware.fsproj
│ ├── LibPackageManager
│ │ ├── InMemory
│ │ │ └── ProgramTypes.fs
│ │ ├── paket.references
│ │ ├── Caching.fs
│ │ └── Stats.fs
│ ├── BuiltinCliHost
│ │ ├── paket.references
│ │ └── Builtin.fs
│ ├── LibBinarySerialization
│ │ ├── paket.references
│ │ └── Serializers
│ │ │ ├── RT
│ │ │ └── PackageValue.fs
│ │ │ └── PT
│ │ │ └── PackageValue.fs
│ ├── LibCloudExecution
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── Init.fs
│ ├── LibConfig
│ │ ├── paket.references
│ │ └── README.md
│ ├── LocalExec
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── Utils.fs
│ ├── BuiltinCloudExecution
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── Builtin.fs
│ ├── BuiltinDarkInternal
│ │ ├── paket.references
│ │ ├── README.md
│ │ └── Helpers
│ │ │ └── Permissions.fs
│ ├── LibClientTypesToCloudTypes
│ │ ├── paket.references
│ │ └── LibClientTypesToCloudTypes.fsproj
│ ├── BuiltinCli
│ │ ├── paket.references
│ │ └── Builtin.fs
│ ├── BuiltinPM
│ │ ├── paket.references
│ │ └── Builtin.fs
│ ├── LibDB
│ │ ├── paket.references
│ │ └── LibDB.fsproj
│ ├── Wasm
│ │ ├── paket.references
│ │ ├── Program.fs
│ │ ├── Builtin.fs
│ │ ├── Init.fs
│ │ └── README.md
│ ├── BuiltinExecution
│ │ ├── paket.references
│ │ └── Libs
│ │ │ └── Bool.fs
│ ├── LibExecution
│ │ ├── paket.references
│ │ └── DarkDateTime.fs
│ ├── Cli
│ │ ├── paket.references
│ │ └── README.md
│ ├── LibParser
│ │ └── paket.references
│ ├── LibService
│ │ ├── README.md
│ │ ├── paket.references
│ │ ├── Init.fs
│ │ ├── Kestrel.fs
│ │ ├── HSTS.fs
│ │ └── FireAndForget.fs
│ ├── Prelude
│ │ ├── paket.references
│ │ ├── Option.fs
│ │ ├── Lazy.fs
│ │ ├── README.md
│ │ ├── HashSet.fs
│ │ ├── ResizeArray.fs
│ │ ├── Tuple2.fs
│ │ ├── Regex.fs
│ │ └── Dictionary.fs
│ └── LibCloud
│ │ ├── README.md
│ │ ├── paket.references
│ │ ├── Init.fs
│ │ ├── DvalReprInternalHash.fs
│ │ └── Password.fs
├── testfiles
│ ├── data
│ │ ├── boring-text
│ │ ├── .gitattributes
│ │ ├── favicon-32x32.png
│ │ └── sample_image_bytes.png
│ ├── execution
│ │ ├── language
│ │ │ ├── basic
│ │ │ │ ├── evariable.dark
│ │ │ │ ├── dfloat.dark
│ │ │ │ ├── estring.dark
│ │ │ │ ├── eand.dark
│ │ │ │ └── eor.dark
│ │ │ ├── collections
│ │ │ │ ├── edict.dark
│ │ │ │ ├── dlist.dark
│ │ │ │ └── dtuple.dark
│ │ │ ├── apply
│ │ │ │ └── einfix.dark
│ │ │ ├── interpreter.dark
│ │ │ └── custom-data
│ │ │ │ └── record-field-acess.dark
│ │ ├── cloud
│ │ │ ├── _middleware.dark
│ │ │ └── _events.dark
│ │ ├── cli
│ │ │ └── file.tests
│ │ └── stdlib
│ │ │ ├── bytes.dark
│ │ │ ├── bool.dark
│ │ │ └── uuid.dark
│ ├── httpclient
│ │ ├── v0
│ │ │ ├── todo
│ │ │ │ ├── readme.md
│ │ │ │ ├── response-redirect-to-ftp.test
│ │ │ │ ├── response-content-type-no-charset.test
│ │ │ │ ├── response-content-type-latin1.test
│ │ │ │ ├── response-content-encoding-invalid.test
│ │ │ │ ├── response-body-invalid-string.test
│ │ │ │ ├── response-body-unicode.test
│ │ │ │ ├── response-redirect-to-same-place-relative.test
│ │ │ │ ├── response-content-type-invalid.test
│ │ │ │ ├── request-query-param-null.test
│ │ │ │ ├── response-header-empty.test
│ │ │ │ ├── response-header-int.test
│ │ │ │ ├── response-redirect-delete.test
│ │ │ │ ├── uri-with-auth-just-username.test
│ │ │ │ ├── response-content-encoding-brotli.test
│ │ │ │ ├── response-header-object.test
│ │ │ │ ├── uri-with-auth-just-password.test
│ │ │ │ ├── response-content-encoding-gzipped.test
│ │ │ │ ├── response-header-string.test
│ │ │ │ ├── uri-with-auth-just-username-with-colon.test
│ │ │ │ ├── response-content-encoding-deflate.test
│ │ │ │ └── request-header-override-content-length-get.test
│ │ │ ├── _request-content-type-invalid.test
│ │ │ ├── response-redirect-to-file.test
│ │ │ ├── basic-head.test
│ │ │ ├── _response-redirect-to-same-place-absolute.test
│ │ │ ├── response-redirect-302.test
│ │ │ ├── response-redirect-306.test
│ │ │ ├── _response-redirect-304.test
│ │ │ ├── response-redirect-303.test
│ │ │ ├── response-redirect-305.test
│ │ │ ├── response-redirect-308.test
│ │ │ ├── response-redirect-300.test
│ │ │ ├── response-redirect-301.test
│ │ │ ├── response-redirect-307.test
│ │ │ ├── basic-get-helper-function.test
│ │ │ ├── basic-get.test
│ │ │ ├── basic-options-helper-function.test
│ │ │ ├── basic-options.test
│ │ │ ├── basic-delete-helper-function.test
│ │ │ ├── basic-delete.test
│ │ │ ├── basic-post.test
│ │ │ ├── basic-post-helper-function.test
│ │ │ ├── _uri-with-path-fragment.test
│ │ │ ├── request-query-param-int.test
│ │ │ ├── uri-with-path-slash.test
│ │ │ ├── request-query-param-float.test
│ │ │ ├── _uri-with-auth-both.test
│ │ │ ├── _request-content-type-empty.test
│ │ │ ├── basic-head-returns-body-helper-function.test
│ │ │ ├── basic-head-returns-body.test
│ │ │ ├── uri-with-path-basic.test
│ │ │ ├── uri-with-path-dots.test
│ │ │ ├── response-header-duplicate.test
│ │ │ ├── basic-patch.test
│ │ │ └── request-form-simple.test
│ │ └── README.md
│ └── httphandler
│ │ ├── query-string.test
│ │ ├── url-http.test
│ │ ├── url-https.test
│ │ ├── injected-icon-post-roundtrip.test
│ │ ├── simple-inline-string-post.test
│ │ ├── response-with-500.test
│ │ ├── simple-injected-string-post.test
│ │ ├── injected-icon-post-length.test
│ │ ├── url-custom-domain.test
│ │ ├── x-forwarded-proto-ignored.test
│ │ ├── simple-response-headers.test
│ │ └── bad-response-just-int.test
├── tests
│ ├── Tests
│ │ ├── paket.references
│ │ └── TestConfig.fs
│ └── TestUtils
│ │ └── paket.references
├── static
│ ├── favicon-32x32.png
│ └── README.md
├── global.json
├── NuGet.Config
├── migrations
│ ├── 20250805_152617_add_scripts_table.sql
│ ├── 20251125_000000_add_account_name.sql
│ ├── 20251119_000000_multi_branch_sync.sql
│ └── 20250820_000000_rename_package_constants_to_values.sql
└── .config
│ └── dotnet-tools.json
├── .dockerignore
├── .github
├── FUNDING.yml
└── dependabot.yml
├── user-code
└── darklang
│ └── scripts
│ ├── add.dark
│ ├── sample-for-testing-extension.dark
│ └── test.dark
├── vscode-extension
├── .gitignore
├── static
│ ├── logo-dark.png
│ ├── logo-dark-transparent.svg
│ └── logo-dark-transparent-low-margin.svg
├── client
│ ├── tsconfig.json
│ └── package.json
├── tsconfig.json
├── .vscodeignore
└── README.md
├── CHANGELOG.md
├── packages
├── darklang
│ ├── vscode
│ │ └── README.md
│ ├── stdlib
│ │ ├── fun.dark
│ │ ├── canvas.dark
│ │ ├── cli
│ │ │ ├── curl.dark
│ │ │ ├── gunzip.dark
│ │ │ └── process.dark
│ │ ├── noModule.dark
│ │ ├── x509.dark
│ │ ├── bytes.dark
│ │ ├── print.dark
│ │ ├── uuid.dark
│ │ ├── alt-json.dark
│ │ └── bool.dark
│ ├── dark-packages.dark
│ ├── modelContextProtocol
│ │ ├── aliases.dark
│ │ └── serverBuilder
│ │ │ ├── aliases.dark
│ │ │ ├── logging.dark
│ │ │ └── state.dark
│ ├── languageServerProtocol
│ │ ├── documentSync
│ │ │ └── README.md
│ │ ├── lifecycle
│ │ │ ├── exit.dark
│ │ │ ├── shutdown.dark
│ │ │ └── initialized.dark
│ │ ├── window
│ │ │ ├── telemetry.dark
│ │ │ └── logMessage.dark
│ │ └── tracing.dark
│ ├── prettyPrinter
│ │ └── canvas.dark
│ ├── cli
│ │ ├── old_notes
│ │ │ ├── README.md
│ │ │ └── _msg.dark
│ │ ├── clear.dark
│ │ ├── quit.dark
│ │ ├── installation
│ │ │ ├── version.dark
│ │ │ └── helpers.dark
│ │ ├── packages
│ │ │ └── display.dark
│ │ └── experiments.dark
│ ├── scm
│ │ ├── branch.dark
│ │ └── packageOps.dark
│ └── languageTools
│ │ ├── common.dark
│ │ └── lsp-server
│ │ ├── aaaa-state.dark
│ │ ├── showDocument.dark
│ │ ├── sync.dark
│ │ └── switchBranch.dark
└── feriel
│ └── modelContextProtocol
│ └── push-notification
│ └── README.md
├── config
├── production
└── local.template
├── canvases
├── dark-editor
│ └── config.yml
└── dark-packages
│ └── config.yml
├── tree-sitter-darklang
├── test
│ └── corpus
│ │ ├── samples
│ │ └── README.md
│ │ ├── _template.txt
│ │ ├── exhaustive
│ │ └── exprs
│ │ │ ├── units.txt
│ │ │ ├── parens.txt
│ │ │ ├── value.txt
│ │ │ ├── char.txt
│ │ │ ├── floats.txt
│ │ │ └── binary_operation.txt
│ │ └── README.md
├── binding.gyp
├── Cargo.toml
└── package.json
├── scripts
├── build
│ ├── clear-all-local-dbs
│ ├── dotnet-fsi
│ ├── clear-dotnet-build
│ ├── dotnet-regen-fsi
│ ├── clear-builder-volumes
│ ├── regenerate-test-files
│ ├── _dotnet-wrapper
│ └── reload-packages
├── devcontainer
│ ├── _write-config-file
│ ├── _create-app-directories
│ ├── _assert-in-container
│ ├── _create-dark-dev-network
│ ├── _setup-circleci-environment
│ ├── _setup-hosts
│ ├── _allow-docker-access
│ ├── _create-cache-directories
│ └── _vscode-post-start-command
├── run-parser-tests
├── linting
│ ├── _check-linked-libs
│ └── yamllinter
├── deployment
│ ├── deploy-lock-all-clear
│ ├── deploy-lock-all-list
│ ├── deploy-lock-one-remove
│ ├── deploy-lock-one-get-name
│ ├── deploy-lock-one-add
│ ├── _deploy-lock-request
│ ├── _notify-deployment-rollbar
│ ├── new-deploy.sh
│ ├── new-build-containers.sh
│ ├── deploy-lock-wait-and-acquire
│ └── new-push-containers.sh
├── migrations
│ ├── mark-not-run
│ └── new
├── contributors
│ └── checkout-pull-request
├── run-backend-datatests
├── stop-second-instance
├── run-prod-exec
├── run-local-exec
├── production
│ └── gcp-get-logs
├── formatting
│ └── pre-commit-hook.sh
├── run-pubsub-emulator
├── installers
│ ├── install-exe-file
│ └── install-gz-file
└── package-extension.sh
├── tf
├── locals.tf
├── artifact_registry.tf
├── README.md
├── main.tf
├── apis.tf
├── vpc.tf
└── custom-domains.tf
├── .style.yapf
├── docs
├── production
│ ├── honeycomb.md
│ ├── deployment.md
│ ├── auditlogs.md
│ └── emergency-login.md
├── benchmarking.md
├── unittests.md
└── release.md
├── .gitattributes
├── .prettierrc.toml
├── .fantomasignore
├── LICENSES
├── .yamllint
├── containers
├── prodexec
│ ├── README.md
│ ├── run.sh
│ └── Dockerfile
├── queueworker
│ └── Dockerfile
├── cronchecker
│ └── Dockerfile
└── bwdserver
│ └── Dockerfile
├── .vscode
├── extensions.json
└── settings.json
├── .circleci
└── gcp-workload-identity-config.json
├── .gitignore
└── .claude
└── settings.local.json
/.prettierignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rundir/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/serialization/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | sqldump*.gz
3 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: darklang
2 |
--------------------------------------------------------------------------------
/backend/src/LibTreeSitter/.gitignore:
--------------------------------------------------------------------------------
1 | lib
--------------------------------------------------------------------------------
/backend/src/LibTreeSitter/paket.references:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/user-code/darklang/scripts/add.dark:
--------------------------------------------------------------------------------
1 | 1L + 2L
--------------------------------------------------------------------------------
/backend/src/DvalReprDeveloper/paket.references:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/testfiles/data/boring-text:
--------------------------------------------------------------------------------
1 | boring text
--------------------------------------------------------------------------------
/vscode-extension/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 | node_modules
--------------------------------------------------------------------------------
/backend/src/ProdExec/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 |
--------------------------------------------------------------------------------
/backend/src/QueueWorker/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
--------------------------------------------------------------------------------
/backend/testfiles/data/.gitattributes:
--------------------------------------------------------------------------------
1 | ** binary
2 |
--------------------------------------------------------------------------------
/backend/src/BwdServer/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 |
--------------------------------------------------------------------------------
/backend/src/CronChecker/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 |
--------------------------------------------------------------------------------
/backend/src/LibClientTypes/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
--------------------------------------------------------------------------------
/backend/src/LibHttpMiddleware/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
--------------------------------------------------------------------------------
/backend/src/LibPackageManager/InMemory/ProgramTypes.fs:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/src/BuiltinCliHost/paket.references:
--------------------------------------------------------------------------------
1 | Ply
2 | FSharp.Core
--------------------------------------------------------------------------------
/backend/src/LibBinarySerialization/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
--------------------------------------------------------------------------------
/backend/src/LibCloudExecution/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 |
--------------------------------------------------------------------------------
/backend/src/LibConfig/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | FsRegex
--------------------------------------------------------------------------------
/backend/src/LocalExec/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | Legivel
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | See the [changelog](https://darklang.com/changelog)
2 |
--------------------------------------------------------------------------------
/backend/src/BuiltinCloudExecution/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 |
--------------------------------------------------------------------------------
/backend/src/BuiltinDarkInternal/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 |
--------------------------------------------------------------------------------
/backend/src/LibClientTypesToCloudTypes/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
--------------------------------------------------------------------------------
/packages/darklang/vscode/README.md:
--------------------------------------------------------------------------------
1 | Interacting with the VS Code API
--------------------------------------------------------------------------------
/backend/src/BuiltinCli/paket.references:
--------------------------------------------------------------------------------
1 | Ply
2 | FSharp.Core
3 | FSharpPlus
--------------------------------------------------------------------------------
/backend/src/BuiltinPM/paket.references:
--------------------------------------------------------------------------------
1 | Ply
2 | FSharp.Core
3 | FSharpPlus
4 |
--------------------------------------------------------------------------------
/config/production:
--------------------------------------------------------------------------------
1 | Production config values are set in tf/service_env_vars.tf
--------------------------------------------------------------------------------
/backend/src/LibDB/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | Microsoft.Data.Sqlite
3 | Fumble
--------------------------------------------------------------------------------
/backend/src/LibPackageManager/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | Microsoft.Data.Sqlite
--------------------------------------------------------------------------------
/backend/src/Wasm/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | Microsoft.AspNetCore.Components.WebAssembly
--------------------------------------------------------------------------------
/canvases/dark-editor/config.yml:
--------------------------------------------------------------------------------
1 | id: 11111111-1111-1111-1111-111111111113
2 | main: main
3 |
--------------------------------------------------------------------------------
/canvases/dark-packages/config.yml:
--------------------------------------------------------------------------------
1 | id: 11111111-1111-1111-1111-111111111112
2 | main: main
3 |
--------------------------------------------------------------------------------
/backend/src/BuiltinExecution/paket.references:
--------------------------------------------------------------------------------
1 | Ply
2 | FSharp.Core
3 | FSharpPlus
4 | Sodium.Core
--------------------------------------------------------------------------------
/backend/src/LibExecution/paket.references:
--------------------------------------------------------------------------------
1 | Ply
2 | FSharp.Core
3 | FSharpPlus
4 | System.IO.Hashing
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/samples/README.md:
--------------------------------------------------------------------------------
1 | A few sample dark programs for reference.
2 |
--------------------------------------------------------------------------------
/backend/src/Cli/paket.references:
--------------------------------------------------------------------------------
1 | Ply
2 | FSharp.Core
3 | FSharpPlus
4 | Microsoft.Data.Sqlite
5 | Fumble
--------------------------------------------------------------------------------
/backend/src/LibParser/paket.references:
--------------------------------------------------------------------------------
1 | Expecto
2 | FSharp.Compiler.Service
3 | NReco.Logging.File
4 |
--------------------------------------------------------------------------------
/backend/tests/Tests/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | FsRegEx
3 | Expecto
4 | SimpleBase
5 | Fumble
6 |
--------------------------------------------------------------------------------
/backend/src/Wasm/Program.fs:
--------------------------------------------------------------------------------
1 | namespace Wasm
2 |
3 | #nowarn "988" // "main module of Program is empty"
4 |
--------------------------------------------------------------------------------
/scripts/build/clear-all-local-dbs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | docker volume rm pgdata pgconf pglogs
4 |
--------------------------------------------------------------------------------
/backend/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darklang/dark/HEAD/backend/static/favicon-32x32.png
--------------------------------------------------------------------------------
/backend/tests/TestUtils/paket.references:
--------------------------------------------------------------------------------
1 | Expecto
2 | FSharp.Compiler.Service
3 | NReco.Logging.File
4 | FsRegEx
--------------------------------------------------------------------------------
/packages/darklang/stdlib/fun.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib.Fun
2 |
3 |
4 | let identity (value: 'a) : 'a = value
--------------------------------------------------------------------------------
/tf/locals.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | project_name = "darklang-next"
3 | project_id = "234768451432"
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/backend/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "8.0.303",
4 | "rollForward": "disable"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/backend/src/BuiltinDarkInternal/README.md:
--------------------------------------------------------------------------------
1 | # BuiltinDarkInternal
2 |
3 | Builtin functions to be used by `dark-editor`.
--------------------------------------------------------------------------------
/backend/src/LibService/README.md:
--------------------------------------------------------------------------------
1 | # LibService
2 |
3 | Common utilities for running an F# service as part of Dark
4 |
--------------------------------------------------------------------------------
/vscode-extension/static/logo-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darklang/dark/HEAD/vscode-extension/static/logo-dark.png
--------------------------------------------------------------------------------
/backend/testfiles/data/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darklang/dark/HEAD/backend/testfiles/data/favicon-32x32.png
--------------------------------------------------------------------------------
/backend/serialization/vanilla_Microsoft-FSharp-Collections-FSharpMap-2-System-String-System-String-_baseline.json:
--------------------------------------------------------------------------------
1 | {
2 | "a": "b"
3 | }
--------------------------------------------------------------------------------
/.style.yapf:
--------------------------------------------------------------------------------
1 | [style]
2 | based_on_style = pep8
3 | indent_width = 2
4 | blank_lines_around_top_level_definition = 2
5 | column_limit = 85
6 |
--------------------------------------------------------------------------------
/backend/serialization/oplist-binary-latest.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darklang/dark/HEAD/backend/serialization/oplist-binary-latest.bin
--------------------------------------------------------------------------------
/backend/src/LocalExec/README.md:
--------------------------------------------------------------------------------
1 | # Local Execution host
2 |
3 | Run local scripts with Backend and special F#/dotnet libraries enabled.
4 |
--------------------------------------------------------------------------------
/backend/testfiles/data/sample_image_bytes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darklang/dark/HEAD/backend/testfiles/data/sample_image_bytes.png
--------------------------------------------------------------------------------
/backend/serialization/toplevels-binary-latest.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darklang/dark/HEAD/backend/serialization/toplevels-binary-latest.bin
--------------------------------------------------------------------------------
/backend/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/docs/production/honeycomb.md:
--------------------------------------------------------------------------------
1 | # Honeycomb notes
2 |
3 | API key is stored in a secret:
4 | https://ui.honeycomb.io/teams/dark/dataset_instructions
5 |
--------------------------------------------------------------------------------
/user-code/darklang/scripts/sample-for-testing-extension.dark:
--------------------------------------------------------------------------------
1 | type ID = Int64
2 | let double (i: Int64) : Int64 = i + i
3 | type MyFloat = Float
4 | 1.5
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/basic/evariable.dark:
--------------------------------------------------------------------------------
1 | (let x = 5L in x) = 5L
2 |
3 | myvar = (Builtin.testDerrorMessage "There is no variable named: myvar")
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *Paket.Restore.targets eol=crlf
2 |
3 | backend/serialization/*.bin linguist-generated=true
4 | backend/serialization/*.json linguist-generated=true
5 |
--------------------------------------------------------------------------------
/backend/src/Prelude/paket.references:
--------------------------------------------------------------------------------
1 | Ply
2 | FSharp.Core
3 | FSharpX.Extras
4 | FSharpPlus
5 | FSharp.SystemTextJson
6 | NodaTime
7 | NodaTime.Serialization.SystemTextJson
--------------------------------------------------------------------------------
/scripts/devcontainer/_write-config-file:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | env | grep DARK_CONFIG | sed 's/^/export /' >> /home/dark/.bashrc
6 |
7 |
--------------------------------------------------------------------------------
/backend/src/Prelude/Option.fs:
--------------------------------------------------------------------------------
1 | module Option
2 |
3 | let unwrap (default' : 'a) (t : Option<'a>) : 'a =
4 | match t with
5 | | None -> default'
6 | | Some value -> value
7 |
--------------------------------------------------------------------------------
/.prettierrc.toml:
--------------------------------------------------------------------------------
1 | tabWidth = 2
2 | printWidth = 80
3 | useTabs = false
4 | semi = true
5 | singleQuote = false
6 | trailingComma = "all"
7 | arrowParens = "avoid"
8 | endOfLine = "lf"
9 |
--------------------------------------------------------------------------------
/backend/src/LibCloud/README.md:
--------------------------------------------------------------------------------
1 | # LibCloud
2 |
3 | The core of the backend application around Dark's Cloud runtime.
4 | Everything from user management, web servers, logging, DBs, etc.
5 |
--------------------------------------------------------------------------------
/backend/src/Prelude/Lazy.fs:
--------------------------------------------------------------------------------
1 | module Lazy
2 |
3 | let inline force (l : Lazy<_>) = l.Force()
4 | let map f l = lazy ((f << force) l)
5 | let bind f l = lazy ((force << f << force) l)
6 |
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/basic/dfloat.dark:
--------------------------------------------------------------------------------
1 | Builtin.testNan != Builtin.testNan = true
2 | Stdlib.Float.multiply -0.0 -1.0 = 0.0
3 | Stdlib.Float.multiply 6.02e22 -10.0 = -6.02e23
--------------------------------------------------------------------------------
/scripts/build/dotnet-fsi:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | cd backend && dotnet fsi --use:../scripts/build/fsi-setup.fsx "${@}"
5 |
--------------------------------------------------------------------------------
/backend/serialization/vanilla_LibCloud-Queue-NotificationData_simple.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "31d72f73-0f99-5a9b-949c-b95705ae7c4d",
3 | "canvasID": "31d72f73-0f99-5a9b-949c-b95705ae7c4d"
4 | }
--------------------------------------------------------------------------------
/backend/src/CronChecker/README.md:
--------------------------------------------------------------------------------
1 | # CronChecker
2 |
3 | Trigger events for scheduled work.
4 |
5 | Until killed, checks for crons that need corresponding jobs enqueued, and enqueues them.
6 |
--------------------------------------------------------------------------------
/scripts/run-parser-tests:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | cd tree-sitter-darklang
7 | npm run test
8 | cd ..
--------------------------------------------------------------------------------
/backend/src/LibCloud/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | PusherServer
3 | System.Diagnostics.DiagnosticSource
4 | FsRegEx
5 | Sodium.Core
6 | Google.Cloud.PubSub.V1
7 | Microsoft.Data.Sqlite
8 | Fumble
--------------------------------------------------------------------------------
/backend/migrations/20250805_152617_add_scripts_table.sql:
--------------------------------------------------------------------------------
1 | -- Scripts
2 | CREATE TABLE IF NOT EXISTS
3 | scripts_v0
4 | ( id TEXT PRIMARY KEY
5 | , name TEXT NOT NULL UNIQUE
6 | , text TEXT NOT NULL
7 | );
--------------------------------------------------------------------------------
/packages/darklang/stdlib/canvas.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Canvas
2 |
3 |
4 | type Program =
5 | { dbs: List
6 | handlers: List }
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/_template.txt:
--------------------------------------------------------------------------------
1 | ==================
2 | [TODO name this test]
3 | ==================
4 |
5 | true
6 |
7 | ---
8 |
9 | (source_file (expression (simple_expression (bool_literal))))
--------------------------------------------------------------------------------
/backend/src/BuiltinCloudExecution/README.md:
--------------------------------------------------------------------------------
1 | # BuiltinCloudExecution
2 |
3 | Standard library functions which need to be run on the backend,
4 | due to their connection to the DB, queues, external internet, etc.
5 |
--------------------------------------------------------------------------------
/packages/darklang/dark-packages.dark:
--------------------------------------------------------------------------------
1 | /// some types that correspond to the `dark-packages` canvas
2 | module Darklang.DarkPackages
3 |
4 | type Stats =
5 | { types: Int64
6 | values: Int64
7 | fns: Int64 }
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/exhaustive/exprs/units.txt:
--------------------------------------------------------------------------------
1 | ==================
2 | unit
3 | ==================
4 |
5 | ()
6 |
7 | ---
8 |
9 | (source_file (expression (simple_expression (unit))))
10 |
11 |
--------------------------------------------------------------------------------
/backend/testfiles/execution/cloud/_middleware.dark:
--------------------------------------------------------------------------------
1 | Http.parseQueryString_v0 "https://darklang.com?x=6&x=7&myString=todo" =
2 | Dict { x = "7"; myString = "todo" }
3 |
4 | Http.parseHeaders_v0 "x: y" = Dict { x = "y" }
--------------------------------------------------------------------------------
/packages/darklang/modelContextProtocol/aliases.dark:
--------------------------------------------------------------------------------
1 | // Common type aliases for Model Context Protocol modules
2 | module Darklang.ModelContextProtocol
3 |
4 | //
5 | type Json = Stdlib.AltJson.Json
6 | //
--------------------------------------------------------------------------------
/docs/production/deployment.md:
--------------------------------------------------------------------------------
1 | # Deploying
2 |
3 | The backend is built into libraries and binaries that use those libraries. We
4 | build containers that use those binaries, then deploy services that use those
5 | containers.
6 |
--------------------------------------------------------------------------------
/scripts/linting/_check-linked-libs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | missing=$(ldd $1)
6 |
7 | if (echo "$missing" | grep not.found) ; then
8 | echo "Missing libraries!"
9 | exit 1
10 | fi
11 |
--------------------------------------------------------------------------------
/tf/artifact_registry.tf:
--------------------------------------------------------------------------------
1 | resource "google_artifact_registry_repository" "production-containers" {
2 | location = "us-central1"
3 | repository_id = "production-containers"
4 | format = "DOCKER"
5 | timeouts {}
6 | }
7 |
--------------------------------------------------------------------------------
/scripts/build/clear-dotnet-build:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -uo pipefail
5 |
6 | rm -Rf backend/Build/*
7 | echo "To build backend/ from scratch, save backend/global.json"
8 |
--------------------------------------------------------------------------------
/backend/serialization/vanilla_System-Tuple-2-System-Guid-Microsoft-FSharp-Collections-FSharpList-1-System-UInt64-_simple.json:
--------------------------------------------------------------------------------
1 | [
2 | "31d72f73-0f99-5a9b-949c-b95705ae7c4d",
3 | [
4 | 1,
5 | 0,
6 | "18446744073709551615"
7 | ]
8 | ]
--------------------------------------------------------------------------------
/backend/serialization/vanilla_System-Tuple-5-System-String-System-String-System-String-NodaTime-Instant-System-Guid-_simple.json:
--------------------------------------------------------------------------------
1 | [
2 | "HTTP",
3 | "/",
4 | "GET",
5 | "2022-07-04T17:46:57Z",
6 | "31d72f73-0f99-5a9b-949c-b95705ae7c4d"
7 | ]
--------------------------------------------------------------------------------
/backend/src/BuiltinDarkInternal/Helpers/Permissions.fs:
--------------------------------------------------------------------------------
1 | /// Helpers for permissions in Dark canvases
2 | module BuiltinDarkInternal.Helpers.Permissions
3 |
4 | open System.Threading.Tasks
5 |
6 | open Prelude
7 | open LibExecution.RuntimeTypes
8 |
--------------------------------------------------------------------------------
/.fantomasignore:
--------------------------------------------------------------------------------
1 | # All .dark files
2 | # (in ./.vscode/* somewhere, we tell VS Code that .dark files are F# files,
3 | # so we get syntax highlighting of the near-equivalent syntax (for now),
4 | # but we don't want Fantomas to format them)
5 | *.dark
--------------------------------------------------------------------------------
/scripts/deployment/deploy-lock-all-clear:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # Clear all deploy locks
5 |
6 | set -euo pipefail
7 |
8 | ./scripts/deployment/_deploy-lock-request / DELETE | jq -r .
--------------------------------------------------------------------------------
/scripts/devcontainer/_create-app-directories:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | RUNDIR="${DARK_CONFIG_RUNDIR}"
6 | mkdir -p "$RUNDIR"
7 | mkdir -p "$RUNDIR/logs"
8 | mkdir -p "$RUNDIR/completed_tests"
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/backend/src/LibCloudExecution/README.md:
--------------------------------------------------------------------------------
1 | # LibCloudExecution
2 |
3 | Pulls together the StdLibs and LibExecution and LibCloud to provide the actual
4 | context we use to execute Dark code in the various Cloud binaries (BwdServer,
5 | QueueWorker, etc).
6 |
--------------------------------------------------------------------------------
/scripts/deployment/deploy-lock-all-list:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # List the deploy locks currently held
5 |
6 | set -euo pipefail
7 |
8 | ./scripts/deployment/_deploy-lock-request / GET | jq -r .[]
--------------------------------------------------------------------------------
/tf/README.md:
--------------------------------------------------------------------------------
1 | # Terraform config
2 |
3 | This is our production terraform. The intent is that this matches the configuration
4 | of everything in our production deployment.
5 |
6 | Note that darklang-classic is in a different project, see classic-tf directory.
--------------------------------------------------------------------------------
/backend/src/QueueWorker/README.md:
--------------------------------------------------------------------------------
1 | # QueueWorker
2 |
3 | Supports user "Workers"/Queues -- users emit events (using `emit`),
4 | and this pulls those events from the queue and runs them.
5 |
6 | The event algorithm in described in [eventsv2.md](/docs/eventsV2.md)
7 |
--------------------------------------------------------------------------------
/scripts/devcontainer/_assert-in-container:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # do not set -euo pipefail here, that's the responsibility of the scripts
4 |
5 | if [[ ! -v IN_DEV_CONTAINER ]]; then
6 | scripts/run-in-docker "${@}"
7 | exit $?
8 | fi
9 |
10 |
--------------------------------------------------------------------------------
/scripts/migrations/mark-not-run:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
4 |
5 | NAME=$1
6 |
7 | psql -d "$DARK_CONFIG_DB_DBNAME" -c "DELETE FROM system_migrations_v0 WHERE name LIKE '%$NAME.sql';"
8 |
--------------------------------------------------------------------------------
/backend/migrations/20251125_000000_add_account_name.sql:
--------------------------------------------------------------------------------
1 | -- Add name column to accounts_v0
2 | ALTER TABLE accounts_v0 ADD COLUMN name TEXT NOT NULL DEFAULT '';
3 | -- Enforce unique usernames
4 | CREATE UNIQUE INDEX IF NOT EXISTS accounts_name_unique ON accounts_v0(name);
5 |
--------------------------------------------------------------------------------
/packages/darklang/stdlib/cli/curl.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib.Cli.Curl
2 |
3 | let downloadFileToPath
4 | (url: String)
5 | (downloadTo: String)
6 | : Stdlib.Result.Result =
7 | Stdlib.Cli.executeWithUnitOrStdErr $"curl -s -L -o \"{downloadTo}\" {url}"
--------------------------------------------------------------------------------
/backend/src/LibHttpMiddleware/README.md:
--------------------------------------------------------------------------------
1 | # LibHttpMiddleware
2 |
3 | HTTP Middleware modules to support BwdServer.
4 |
5 | Designed to move as much of the HTTP framework into "user space"
6 | (or something which could potentially be user space in the future)
7 | as possible.
8 |
--------------------------------------------------------------------------------
/user-code/darklang/scripts/test.dark:
--------------------------------------------------------------------------------
1 | val myList = [1L; 2L; 3L]
2 | val recordVal =
3 | Stdlib.Cli.Host.Host {
4 | os = Stdlib.Cli.OS.OS.Linux;
5 | architecture = Stdlib.Cli.Architecture.Architecture.X86_64;
6 | defaultShell = Stdlib.Cli.Shell.Shell.Bash
7 | }
8 |
--------------------------------------------------------------------------------
/backend/src/DvalReprDeveloper/README.md:
--------------------------------------------------------------------------------
1 | # DvalReprDeveloper
2 |
3 | Various stringifications from `LibExecution.RuntimeTypes`.
4 |
5 | CLEANUP all of this should be replacd with Darklang code eventually.
6 | It's just a bit cumbersome to do that migration, so punting it for later.
7 |
--------------------------------------------------------------------------------
/scripts/migrations/new:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
4 |
5 | NAME=$1
6 | DATE=$(date -u +%Y%m%d_%H%M%S)
7 |
8 | FILE=backend/migrations/${DATE}_${NAME}.sql
9 | touch "${FILE}"
10 | git add "${FILE}"
11 |
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/collections/edict.dark:
--------------------------------------------------------------------------------
1 | ((Dict { a = 5L }) |> Stdlib.Dict.get "a") = Stdlib.Option.Option.Some 5L
2 |
3 | ((Dict { ___ = 5L }) |> Stdlib.Dict.get "") = Stdlib.Option.Option.Some 5L
4 |
5 | ((Dict { a = 5L }) |> Stdlib.Dict.get "b") = Stdlib.Option.Option.None
--------------------------------------------------------------------------------
/LICENSES:
--------------------------------------------------------------------------------
1 | For a license for this repo, see the LICENSE.md file.
2 |
3 | The standard library is, in part, based on the Elm Standard Library, which
4 | is Copyright 2014-present Evan Czaplicki under the BSD 3-Clause "New" or
5 | "Revised" License. See https://github.com/elm/core/blob/1.0.5/LICENSE.
6 |
--------------------------------------------------------------------------------
/backend/src/LibConfig/README.md:
--------------------------------------------------------------------------------
1 | # LibConfig
2 |
3 | Most config values are only useful for _services_, and are thus in LibService,
4 | but a few adjustable things are also relevant to our CLI app (along with, future,
5 | our WASM platform), so those values go here. All of these should have defaults.
--------------------------------------------------------------------------------
/scripts/build/dotnet-regen-fsi:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | cd backend
7 | rm -f paket-files/paket.restore.cached
8 | dotnet restore fsdark.sln
9 | dotnet paket generate-load-scripts --framework net8.0
10 |
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/README.md:
--------------------------------------------------------------------------------
1 | Run these with `npm run test` in the `tree-sitter-darklang` directory.
2 |
3 | ---
4 |
5 | Note:
6 |
7 | It's a `tree-sitter`-ism to keep these test files either in `./corpus` or `./test/corpus`.
8 | I settled on following this, and choosing the latter.
9 |
--------------------------------------------------------------------------------
/backend/serialization/vanilla_LibService-Rollbar-HoneycombJson_simple.json:
--------------------------------------------------------------------------------
1 | {
2 | "filters": [
3 | {
4 | "column": "trace.trace_id",
5 | "op": "=",
6 | "value": "31d72f73-0f99-5a9b-949c-b95705ae7c4d"
7 | }
8 | ],
9 | "limit": 100,
10 | "time_range": 604800
11 | }
--------------------------------------------------------------------------------
/backend/src/Prelude/README.md:
--------------------------------------------------------------------------------
1 | # Prelude
2 |
3 | To use, `open Prelude` in other modules.
4 |
5 | This adds missing methods and functions to existing standard modules, much like FSharpPlus.
6 |
7 | Eventually this might become the thing we open in all files, encompassing FSharpPlus and others.
8 |
9 |
--------------------------------------------------------------------------------
/packages/darklang/stdlib/noModule.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib
2 |
3 |
4 | /// Returns true if the two value are equal
5 | let equals (a: 'a) (b: 'a) : Bool = Builtin.equals a b
6 |
7 |
8 | /// Returns true if the two value are not equal
9 | let notEquals (a: 'a) (b: 'a) : Bool = Builtin.notEquals a b
--------------------------------------------------------------------------------
/packages/darklang/stdlib/x509.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib.X509
2 |
3 | /// Extract the public key from a PEM encoded certificate and return the key in PEM format.
4 | let pemCertificatePublicKey
5 | (cert: String)
6 | : Stdlib.Result.Result =
7 | Builtin.x509PemCertificatePublicKey cert
--------------------------------------------------------------------------------
/vscode-extension/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es2020",
5 | "lib": ["es2020"],
6 | "outDir": "out",
7 | "rootDir": "src",
8 | "sourceMap": true
9 | },
10 | "include": ["src"],
11 | "exclude": ["node_modules"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/darklang/stdlib/bytes.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib.Bytes
2 |
3 |
4 | /// Hex (Base16) encodes using an uppercase alphabet. Complies
5 | /// with [RFC 4648 section 8](https://www.rfc-editor.org/rfc/rfc4648.html#section-8
6 | let hexEncode (bytes: List) : String = Builtin.bytesHexEncode bytes
--------------------------------------------------------------------------------
/packages/darklang/languageServerProtocol/documentSync/README.md:
--------------------------------------------------------------------------------
1 | Note: there's a clear line drawn in the spec between:
2 |
3 | - text documents (what you normally work with)
4 | - notebooks (those interactive things like "IPython notebooks")
5 |
6 | There's overlap between the two, but they're generally different things here.
7 |
--------------------------------------------------------------------------------
/packages/darklang/stdlib/print.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib
2 |
3 |
4 | let print (str: String): Unit =
5 | Builtin.print str
6 |
7 |
8 | let printLine (str: String): Unit =
9 | Builtin.printLine str
10 |
11 |
12 | let printLines (lines: List): Unit =
13 | lines
14 | |> List.iter(fun l -> printLine l)
15 |
--------------------------------------------------------------------------------
/scripts/devcontainer/_create-dark-dev-network:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | NETWORK=dark-dev-net
6 |
7 | EXISTING=$(docker network ls --filter name=$NETWORK -q)
8 | if [[ $EXISTING == "" ]]; then
9 | echo "Creating docker network $NETWORK"
10 | docker network create $NETWORK
11 | fi
12 |
13 |
--------------------------------------------------------------------------------
/backend/migrations/20251119_000000_multi_branch_sync.sql:
--------------------------------------------------------------------------------
1 |
2 | ALTER TABLE package_ops ADD COLUMN instance_id TEXT NULL
3 | REFERENCES instances(id) ON DELETE SET NULL;
4 |
5 | -- Create index for querying ops by instance
6 | CREATE INDEX IF NOT EXISTS idx_package_ops_instance
7 | ON package_ops(instance_id) WHERE instance_id IS NOT NULL;
8 |
--------------------------------------------------------------------------------
/backend/tests/Tests/TestConfig.fs:
--------------------------------------------------------------------------------
1 | module Tests.TestConfig
2 |
3 | open LibConfig.ConfigDsl
4 |
5 | // testing
6 | let bwdServerBackendPort = int "DARK_CONFIG_TEST_BWDSERVER_BACKEND_PORT"
7 | let bwdServerKubernetesPort = int "DARK_CONFIG_TEST_BWDSERVER_KUBERNETES_PORT"
8 | let httpClientPort = int "DARK_CONFIG_TEST_HTTPCLIENT_SERVER_PORT"
9 |
--------------------------------------------------------------------------------
/scripts/deployment/deploy-lock-one-remove:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # Remove the deploy lock for this commit
5 |
6 | set -euo pipefail
7 |
8 | LOCKNAME=$(./scripts/deployment/deploy-lock-one-get-name)
9 |
10 | ./scripts/deployment/_deploy-lock-request "/${LOCKNAME}" DELETE | jq -r .
--------------------------------------------------------------------------------
/vscode-extension/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es2020",
5 | "lib": ["es2020"],
6 | "outDir": "out",
7 | "rootDir": "src",
8 | "sourceMap": true
9 | },
10 | "include": ["src"],
11 | "exclude": ["node_modules"],
12 | "references": [
13 | { "path": "./client" },
14 | ]
15 | }
--------------------------------------------------------------------------------
/backend/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "paket": {
6 | "version": "9.0.2",
7 | "commands": [
8 | "paket"
9 | ]
10 | },
11 | "dotnet-trace": {
12 | "version": "9.0.553101",
13 | "commands": [
14 | "dotnet-trace"
15 | ]
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/packages/darklang/prettyPrinter/canvas.dark:
--------------------------------------------------------------------------------
1 | // TODO:
2 | //alias PT = LanguageTools.ProgramTypes
3 | //alias RT = Stdlib.RuntimeTypes
4 |
5 | module Darklang.PrettyPrinter
6 |
7 | let canvas (c: Canvas.Program) : String =
8 | // need to look at the names of all types and functions,
9 | // and figure out module tree before actually printing stuff
10 | "TODO"
--------------------------------------------------------------------------------
/scripts/deployment/deploy-lock-one-get-name:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # Returns the name of the lock-file for this commit
5 |
6 | COMMIT=$(git rev-parse --short HEAD)
7 | TIMESTAMP=$(git show -s --format=%at HEAD)
8 | LOCKFILE_ID="${TIMESTAMP}-${COMMIT}"
9 |
10 | echo "deploy-lock-${LOCKFILE_ID}"
11 |
--------------------------------------------------------------------------------
/backend/src/Wasm/Builtin.fs:
--------------------------------------------------------------------------------
1 | module Wasm.Builtin
2 |
3 | open Prelude
4 | open LibExecution.RuntimeTypes
5 |
6 | module Builtin = LibExecution.Builtin
7 |
8 |
9 | let fnRenames : Builtin.FnRenames =
10 | // old names, new names
11 | // eg: fn "Http" "respond" 0, fn "Http" "response" 0
12 | []
13 |
14 | let builtins = Builtin.combine [ Libs.Editor.builtins ] fnRenames
15 |
--------------------------------------------------------------------------------
/backend/testfiles/execution/cli/file.tests:
--------------------------------------------------------------------------------
1 | module Write =
2 | let testContents () : String = "Test conrents"
3 |
4 | (let filename = (Builtin.File.createTemp ()) |> Builtin.unwrap
5 | do (testContents ()) |> Stdlib.String.toBytes |> (Builtin.File.write filename)
6 | Builtin.fileRead filename) = Stdlib.Result.Result.Ok(
7 | (testContents ()) |> Stdlib.String.toBytes
8 | )
--------------------------------------------------------------------------------
/scripts/devcontainer/_setup-circleci-environment:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | # build-server does an equivalent to this in the dev environment
6 |
7 | ENV_FILE="config/circleci"
8 | echo "Using env: $ENV_FILE"
9 |
10 | grep DARK_CONFIG "$ENV_FILE" | sed 's/^\(DARK_CONFIG_[A-Z_]*\)=\(.*\)$/if [[ ! -v \1 ]]; then export \1=\2; fi/' >> "${BASH_ENV}"
11 |
--------------------------------------------------------------------------------
/packages/darklang/cli/old_notes/README.md:
--------------------------------------------------------------------------------
1 | This is a collection of old code/notes that I've had stashed locally.
2 |
3 | I'd like to get them off of my computer, so committing them here for now
4 | as a gentle reminder long-term to revisit and reduce.
5 |
6 | (I think there are things in these remaining files that would be worth
7 | reincorporating in some fashion but it's not high-priority to.)
--------------------------------------------------------------------------------
/backend/testfiles/httpclient/v0/todo/readme.md:
--------------------------------------------------------------------------------
1 | These test files were copied over from `httpclient/v5` tests. I've been reviewing
2 | these one by one, seeing if they make sense to test against the HttpClient.
3 |
4 | Many of these may be best to just ignore/delete - for example, query params are
5 | input differently now (just as part of the URL) and likely don't need so many
6 | test files.
7 |
--------------------------------------------------------------------------------
/tf/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.6.0"
3 |
4 | required_providers {
5 | google = "5.4.0"
6 | }
7 | }
8 |
9 | provider "google" {
10 | project = local.project_name
11 | region = "us-central1"
12 | }
13 |
14 | terraform {
15 | cloud {
16 | organization = "darklang"
17 |
18 | workspaces {
19 | name = "darklang"
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/backend/src/BuiltinCliHost/Builtin.fs:
--------------------------------------------------------------------------------
1 | module BuiltinCliHost.Builtin
2 |
3 | open Prelude
4 | open LibExecution.RuntimeTypes
5 |
6 | module Builtin = LibExecution.Builtin
7 |
8 |
9 | let fnRenames : Builtin.FnRenames =
10 | // old names, new names
11 | // eg: fn "Http" "respond" 0, fn "Http" "response" 0
12 | []
13 |
14 | let builtins = Builtin.combine [ Libs.Cli.builtins ] fnRenames
15 |
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/exhaustive/exprs/parens.txt:
--------------------------------------------------------------------------------
1 | ==================
2 | parens expr
3 | ==================
4 |
5 | (true)
6 |
7 | ---
8 |
9 | (source_file
10 | (expression
11 | (simple_expression
12 | (paren_expression
13 | (symbol)
14 | (expression (simple_expression (bool_literal)))
15 | (symbol)
16 | )
17 | )
18 | )
19 | )
20 |
21 |
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/exhaustive/exprs/value.txt:
--------------------------------------------------------------------------------
1 | ==================
2 | package value
3 | ==================
4 |
5 | Stdlib.List.empty
6 |
7 | ---
8 |
9 | (source_file
10 | (expression
11 | (simple_expression
12 | (qualified_val_or_fn_name
13 | (module_identifier) (symbol) (module_identifier) (symbol) (value_or_fn_identifier)
14 | )
15 | )
16 | )
17 | )
--------------------------------------------------------------------------------
/scripts/devcontainer/_setup-hosts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | echo 127.0.0.1 dlio.localhost | sudo tee -a /etc/hosts
6 | echo 127.0.0.1 test.dlio.localhost | sudo tee -a /etc/hosts
7 | echo 127.0.0.1 dark-editor.dlio.localhost | sudo tee -a /etc/hosts
8 | echo 127.0.0.1 dark-repl.dlio.localhost | sudo tee -a /etc/hosts
9 | echo 127.0.0.1 dark-packages.dlio.localhost | sudo tee -a /etc/hosts
--------------------------------------------------------------------------------
/scripts/contributors/checkout-pull-request:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -euo pipefail
3 |
4 | # Not running in container cause git creds aren't in there
5 |
6 | NUM=$1
7 | LOCAL_BRANCH="pr-${NUM}"
8 | REMOTE_BRANCH="pull/${NUM}/head"
9 |
10 |
11 | git checkout main
12 |
13 | git branch -D "pr-${NUM}" || true
14 | git fetch origin "${REMOTE_BRANCH}:${LOCAL_BRANCH}"
15 | git checkout "${LOCAL_BRANCH}"
16 |
17 |
--------------------------------------------------------------------------------
/scripts/deployment/deploy-lock-one-add:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # Add a lock identifier for the commit and the timestamp.
5 |
6 | set -euo pipefail
7 |
8 | LOCKNAME=$(./scripts/deployment/deploy-lock-one-get-name)
9 |
10 | echo "Adding lock file with name ${LOCKNAME}"
11 |
12 | ./scripts/deployment/_deploy-lock-request "/${LOCKNAME}" POST | jq -r .
--------------------------------------------------------------------------------
/scripts/build/clear-builder-volumes:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | # Clear all the volumes that we use
6 |
7 | # Must be run from outside (stopped) container
8 |
9 | docker volume rm \
10 | dark_build \
11 | dark_nuget \
12 | tree-sitter-build \
13 | tree-sitter-node-modules \
14 | darklang-dark-extension-volume \
15 | darklang-dark-extension-volume-insiders \
16 | vscode
17 |
--------------------------------------------------------------------------------
/packages/darklang/stdlib/cli/gunzip.dark:
--------------------------------------------------------------------------------
1 | /// Functions to interact with the `gunzip` CLI application
2 | module Darklang.Stdlib.Cli.Gunzip
3 |
4 |
5 | /// Unzip a file to a specified destination path
6 | let unzipToFile
7 | (inputFilePath: String)
8 | (outputFilePath: String)
9 | : Stdlib.Result.Result =
10 | Stdlib.Cli.executeWithUnitOrStdErr
11 | $"gunzip -c {inputFilePath} > {outputFilePath}"
--------------------------------------------------------------------------------
/backend/src/LibService/paket.references:
--------------------------------------------------------------------------------
1 | FSharp.Core
2 | FsRegex
3 | Rollbar
4 | Rollbar.NetCore.AspNet
5 | Honeycomb.OpenTelemetry
6 | OpenTelemetry
7 | OpenTelemetry.Exporter.OpenTelemetryProtocol
8 | OpenTelemetry.Exporter.Console
9 | OpenTelemetry.Instrumentation.AspNetCore
10 | OpenTelemetry.Extensions.Hosting
11 | OpenTelemetry.Instrumentation.Http
12 | Microsoft.Extensions.Diagnostics.HealthChecks
13 | LaunchDarkly.ServerSdk
--------------------------------------------------------------------------------
/backend/src/Wasm/Init.fs:
--------------------------------------------------------------------------------
1 | namespace Wasm
2 |
3 | open Microsoft.JSInterop
4 |
5 | open Prelude
6 |
7 | type Init =
8 | []
9 | static member InitializeDarkRuntime() : unit =
10 | System.Environment.SetEnvironmentVariable("TZ", "UTC")
11 | Json.Vanilla.allow
12 | "to 'Export' the editor - just for debugging"
13 | System.Console.WriteLine("Dark runtime initialized")
14 |
--------------------------------------------------------------------------------
/packages/darklang/languageServerProtocol/lifecycle/exit.dark:
--------------------------------------------------------------------------------
1 | (*
2 | /// The exit event is sent from the client to the server to
3 | /// ask the server to exit its process.
4 | export namespace ExitNotification {
5 | export const method: 'exit' = 'exit';
6 | export const messageDirection: MessageDirection = MessageDirection.clientToServer;
7 | export const type = new ProtocolNotificationType0(method);
8 | }
9 | *)
--------------------------------------------------------------------------------
/scripts/devcontainer/_allow-docker-access:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | if [[ -S "/var/run/docker.sock" ]]; then
6 | sudo chmod 777 /var/run/docker.sock
7 | else
8 | # We might not have the docker socket available on windows. Since we don't
9 | # need this all that much, let's just print a warning rather than expect
10 | # people to set this up.
11 | echo "No docker socket, skipping"
12 | fi
13 |
--------------------------------------------------------------------------------
/tf/apis.tf:
--------------------------------------------------------------------------------
1 | variable "google_cloud_services" {
2 | type = set(string)
3 | default = [
4 | "compute.googleapis.com",
5 | "secretmanager.googleapis.com",
6 | "run.googleapis.com"
7 | ]
8 | }
9 |
10 | resource "google_project_service" "apis" {
11 | for_each = toset(var.google_cloud_services)
12 | provider = google
13 | service = each.value
14 | disable_on_destroy = false
15 | }
16 |
--------------------------------------------------------------------------------
/.yamllint:
--------------------------------------------------------------------------------
1 | extends: default
2 |
3 | rules:
4 | line-length: disable
5 | document-start: disable
6 | indentation:
7 | spaces: 2
8 | indent-sequences: true
9 | key-duplicates: enable
10 | brackets:
11 | min-spaces-inside: 0
12 | max-spaces-inside: 0
13 | comments:
14 | require-starting-space: true
15 | min-spaces-from-content: 1
16 | braces:
17 | min-spaces-inside: 1
18 | max-spaces-inside: 1
19 |
--------------------------------------------------------------------------------
/backend/src/LibCloud/Init.fs:
--------------------------------------------------------------------------------
1 | module LibCloud.Init
2 |
3 | open System.Threading.Tasks
4 | open FSharp.Control.Tasks
5 |
6 | open Prelude
7 |
8 | let init (serviceName : string) : Task =
9 | task {
10 | printTime $"Initing LibCloud in {serviceName}"
11 |
12 | let queueTask = Queue.init ()
13 | let! (_ : List) = Task.flatten [ queueTask ]
14 |
15 | printTime $" Inited LibCloud in {serviceName}"
16 | }
17 |
--------------------------------------------------------------------------------
/backend/src/ProdExec/README.md:
--------------------------------------------------------------------------------
1 | # Prod Execution Host
2 |
3 | Based on
4 | https://andrewlock.net/deploying-asp-net-core-applications-to-kubernetes-part-10-creating-an-exec-host-deployment-for-running-one-off-commands/,
5 | this is an executable which runs on a container in production, that can be used
6 | for one off tasks. To start with, the one-off tasks are:
7 |
8 | - run migrations
9 | - emergency login if auth provider is down
10 |
--------------------------------------------------------------------------------
/backend/src/LibCloudExecution/Init.fs:
--------------------------------------------------------------------------------
1 | /// Initialize LibCloudExecution
2 | module LibCloudExecution.Init
3 |
4 | open FSharp.Control.Tasks
5 | open System.Threading.Tasks
6 |
7 | open Prelude
8 |
9 | let init (serviceName : string) : Task =
10 | task {
11 | printTime $"Initing LibCloudExecution in {serviceName}"
12 | do! CloudExecution.init ()
13 | printTime $" Inited LibCloudExecution in {serviceName}"
14 | return ()
15 | }
16 |
--------------------------------------------------------------------------------
/packages/darklang/cli/clear.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Cli.Clear
2 |
3 |
4 | let execute (state: AppState) (args: List) : AppState =
5 | Builtin.stdoutClear ()
6 | { state with needsFullRedraw = true }
7 |
8 |
9 | let complete (_state: AppState) (_args: List) : List =
10 | []
11 |
12 |
13 | let help (_state: AppState) : Unit =
14 | [
15 | "Usage: clear"
16 | "Clear the terminal screen."
17 | ] |> Stdlib.printLines
18 |
--------------------------------------------------------------------------------
/tree-sitter-darklang/binding.gyp:
--------------------------------------------------------------------------------
1 | {
2 | "targets": [{
3 | "target_name": "tree_sitter_darklang_binding",
4 | "include_dirs": [") : AppState =
5 | Stdlib.printLine "Goodbye!"
6 | { state with isExiting = true }
7 |
8 |
9 | let complete (_state: AppState) (_args: List) : List =
10 | []
11 |
12 |
13 | let help (_state: AppState) : Unit =
14 | [
15 | "Usage: quit"
16 | "Exit the CLI immediately."
17 | ] |> Stdlib.printLines
18 |
19 |
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/collections/dlist.dark:
--------------------------------------------------------------------------------
1 | [] = []
2 |
3 | [ 1L ] = [ 1L ]
4 |
5 | [ 1L; 2L ] = [ 1L; 2L ]
6 |
7 | [ 5L; Stdlib.Int64.add_v0 1L 5L; 0L ] = [ 5L; 6L; 0L ]
8 |
9 | [ 5L; Builtin.testRuntimeError "test"; 0L ] =
10 | Builtin.testDerrorMessage "Uncaught exception: test"
11 |
12 | [ 5L; Builtin.testRuntimeError "1"; Builtin.testRuntimeError "2" ] =
13 | Builtin.testDerrorMessage "Uncaught exception: 1"
14 |
15 | // TODO mixed data attempts
--------------------------------------------------------------------------------
/scripts/run-backend-datatests:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | trap ctrl_c INT
7 |
8 | function ctrl_c() {
9 | killall -9 Tests
10 | exit 1
11 | }
12 |
13 | killall -9 Tests || true
14 |
15 | EXE=Build/out/DataTests/Debug/net8.0/linux-x64/DataTests
16 |
17 | # No migrations
18 |
19 | cd backend
20 |
21 | DARK_CONFIG_TELEMETRY_EXPORTER=none \
22 | "${EXE}" --no-spinner "${@}"
23 |
--------------------------------------------------------------------------------
/backend/src/BuiltinCloudExecution/Builtin.fs:
--------------------------------------------------------------------------------
1 | /// Builtin functions that can only be run on the backend
2 | ///
3 | /// Aggregates functions in other modules
4 | module BuiltinCloudExecution.Builtin
5 |
6 | module Builtin = LibExecution.Builtin
7 |
8 | let fnRenames : Builtin.FnRenames =
9 | // old names, new names
10 | // eg: fn "Http" "respond" 0, fn "Http" "response" 0
11 | []
12 |
13 | let builtins = Builtin.combine [ Libs.DB.builtins; Libs.Event.builtins ] fnRenames
14 |
--------------------------------------------------------------------------------
/backend/src/LibCloud/DvalReprInternalHash.fs:
--------------------------------------------------------------------------------
1 | module LibExecution.DvalReprInternalHash
2 |
3 | open Prelude
4 |
5 | let supportedHashVersions : int list = [ 2 ]
6 |
7 | let currentHashVersion : int = 2
8 |
9 | let hash (version : int) (arglist : NEList) : string =
10 | match version with
11 | | 2 -> arglist |> NEList.toList |> DvalReprInternalRoundtrippable.toHashV2
12 | | _ -> Exception.raiseInternal $"Invalid Dval.hash version" [ "version", version ]
13 |
--------------------------------------------------------------------------------
/backend/src/Prelude/HashSet.fs:
--------------------------------------------------------------------------------
1 | module HashSet
2 |
3 | type HashSet<'v> = System.Collections.Generic.HashSet<'v>
4 |
5 | let add (v : 'v) (s : HashSet<'v>) : unit =
6 | let (_ : bool) = s.Add v
7 | ()
8 |
9 | let empty () : HashSet<'v> = System.Collections.Generic.HashSet<'v>()
10 |
11 | let toList (d : HashSet<'v>) : List<'v> =
12 | seq {
13 | let mutable e = d.GetEnumerator()
14 |
15 | while e.MoveNext() do
16 | yield e.Current
17 | }
18 | |> Seq.toList
19 |
--------------------------------------------------------------------------------
/scripts/stop-second-instance:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # TODO remove this and run-second-instance
5 | # (temporary until we have a 'real' server standing.)
6 |
7 | set -euo pipefail
8 |
9 | INSTANCE_DB="data-instance2.db"
10 |
11 | green="\033[0;32m"
12 | reset="\033[0m"
13 |
14 | echo -e "${green}Stopping instance2...${reset}"
15 | pkill -f "DARK_CONFIG_DB_NAME=${INSTANCE_DB}" || true
16 | echo -e "${green}Done${reset}"
17 |
--------------------------------------------------------------------------------
/packages/darklang/modelContextProtocol/serverBuilder/aliases.dark:
--------------------------------------------------------------------------------
1 | // Common type aliases for ServerBuilder modules
2 | module Darklang.ModelContextProtocol.ServerBuilder
3 |
4 | //
5 | type Json = Stdlib.AltJson.Json
6 | type McpServerBuilder = Darklang.ModelContextProtocol.ServerBuilder.State.McpServerBuilder
7 | type BuilderServerState = Darklang.ModelContextProtocol.ServerBuilder.State.BuilderServerState
8 | type Logging = Darklang.ModelContextProtocol.ServerBuilder.Logging
9 | //
--------------------------------------------------------------------------------
/backend/src/LibCloud/Password.fs:
--------------------------------------------------------------------------------
1 | module LibCloud.Password
2 |
3 | open Prelude
4 |
5 | type T =
6 | private
7 | | Pw of string
8 |
9 | override this.ToString() : string =
10 | let (Pw pw) = this
11 | pw
12 |
13 | let fromPlaintext (password : string) : T =
14 | password
15 | |> Sodium.PasswordHash.ArgonHashString
16 | |> UTF8.toBytes
17 | |> Base64.defaultEncodeToString
18 | |> Pw
19 |
20 | let invalid : T = Pw ""
21 |
22 | let fromHash (hash : string) : T = Pw hash
23 |
--------------------------------------------------------------------------------
/containers/prodexec/README.md:
--------------------------------------------------------------------------------
1 | # ProdExec container
2 |
3 | The prodexec container runs as service in Cloud Run. It's purpose is to ssh into it
4 | so we can run commands like DB migrations.
5 |
6 | Since Cloud Run doesn't allow ssh access, we tunnel it through http using chisel. For
7 | security, it should only be accessible via google cloud, and never on the public
8 | internet.
9 |
10 | To connect, run ./scripts/production/connect-to-prod-exec, which will ssh you in if you have
11 | permission to do so.
--------------------------------------------------------------------------------
/backend/src/BwdServer/README.md:
--------------------------------------------------------------------------------
1 | # BwdServer
2 |
3 | This is the webserver for darklang.io, often referred to as "BWD"
4 | (named after our old domain - builtwithdark.com).
5 |
6 | All Dark HTTP Handlers hosted by our cloud are hosted with BWD -
7 | our grand-users hit this server, and BWD handles the requests.
8 |
9 | So, BWD is what handles the HTTP "handlers" of a Dark program.
10 |
11 | It uses ASP.NET directly, instead of a web framework,
12 | so we can tune the exact behaviour of headers and such.
13 |
--------------------------------------------------------------------------------
/backend/src/Wasm/README.md:
--------------------------------------------------------------------------------
1 | # Wasm
2 |
3 | Some of Dark's "backend" F# source code is compiled to WebAssemby to be usable by JS.
4 |
5 | In Dark-Classic, it was used to support "analysis," in-editor immediate debugging
6 | that looped in 'traces' -- recordings of the inputs/outputs of fn calls in the
7 | eval of a Handler (HTTP, Cron, Queue, Script).
8 |
9 | We'll likely use this for something similar in the new iteration of Dark, but
10 | haven't used it quite yet, so this project is sitting around until we need it.
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/exhaustive/exprs/char.txt:
--------------------------------------------------------------------------------
1 | ==================
2 | basic char
3 | ==================
4 |
5 | 'a'
6 |
7 | ---
8 |
9 | (source_file
10 | (expression
11 | (simple_expression (char_literal (symbol) (character) (symbol)))))
12 |
13 |
14 | ==================
15 | escape sequence
16 | ==================
17 |
18 | '\n'
19 |
20 | ---
21 |
22 | (source_file
23 | (expression
24 | (simple_expression (char_literal (symbol) (character (char_or_string_escape_sequence)) (symbol)))))
--------------------------------------------------------------------------------
/backend/static/README.md:
--------------------------------------------------------------------------------
1 | # `backend/static`
2 |
3 | This directory contains static files that are served by a Dark backend for a webpage.
4 | The `dark_wasm` and `tree-sitter` directories should ideally be hosted in a CDN, long-term.
5 |
6 | These assets are currently served by an experimental canvas, `dark-serve-static`.
7 | See the README.md in that directory for more information.
8 |
9 | ## Tree-Sitter WebAssembly/JS Bindings
10 |
11 | If you don't see a `tree-sitter` directory, run `./scripts/build/build-parser`.
--------------------------------------------------------------------------------
/backend/testfiles/httpclient/v0/todo/response-redirect-to-ftp.test:
--------------------------------------------------------------------------------
1 | [expected-request]
2 | GET PATH HTTP/1.1
3 | Accept: */*
4 | Accept-Encoding: deflate, gzip, br
5 | Content-Type: text/plain; charset=utf-8
6 | Host: HOST
7 |
8 | [response]
9 | HTTP/1.1 302 Found
10 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
11 | Location: ftp://speedtest.tele2.net/1KB.zip
12 |
13 |
14 | [test]
15 | (match Darklang.Stdlib.HttpClient.request "get" "http://URL" [] [] with
16 | | Ok _ -> "fail"
17 | | Error response -> response) = "Unsupported protocol"
18 |
--------------------------------------------------------------------------------
/scripts/run-prod-exec:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | PUBLISHED=false
7 |
8 | for i in "$@"
9 | do
10 | case "${i}" in
11 | --published)
12 | PUBLISHED=true
13 | shift
14 | ;;
15 | esac
16 | done
17 |
18 | if [[ "$PUBLISHED" == "true" ]]; then
19 | EXE="backend/Build/out/ProdExec/Release/net8.0/linux-x64/publish/ProdExec"
20 | else
21 | EXE="backend/Build/out/ProdExec/Debug/net8.0/ProdExec"
22 | fi
23 |
24 | "${EXE}" "$@"
25 |
--------------------------------------------------------------------------------
/backend/testfiles/httpclient/v0/todo/response-content-type-no-charset.test:
--------------------------------------------------------------------------------
1 | [expected-request]
2 | GET PATH HTTP/1.1
3 | Accept: */*
4 | Accept-Encoding: deflate, gzip, br
5 | Content-Type: text/plain; charset=utf-8
6 | Host: HOST
7 |
8 | [response]
9 | HTTP/1.1 200 OK
10 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
11 | Content-type: text/plain
12 | Content-Length: LENGTH
13 |
14 | à æ ç
15 |
16 | [test]
17 | (let response = (Darklang.Stdlib.HttpClient.request "get" "http://URL" [] []) |> Builtin.unwrap
18 | response.body) =
19 | "à æ ç"
20 |
--------------------------------------------------------------------------------
/scripts/devcontainer/_create-cache-directories:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | prepare () {
6 | sudo mkdir -p $1
7 |
8 | # sudo chown -R dark:dark $1
9 | # note: we updated from the above to the below because of some symlinked
10 | # tree-sitter binary in the tsd/node_modules dir
11 |
12 | sudo find "$1" ! -type l -exec chown dark:dark {} +
13 | }
14 |
15 | prepare "backend/Build"
16 | prepare "/home/dark/.nuget"
17 | prepare "tree-sitter-darklang/build"
18 | prepare "tree-sitter-darklang/node_modules"
19 |
--------------------------------------------------------------------------------
/backend/testfiles/httpclient/v0/todo/response-content-type-latin1.test:
--------------------------------------------------------------------------------
1 | [expected-request]
2 | GET PATH HTTP/1.1
3 | Accept: */*
4 | Accept-Encoding: deflate, gzip, br
5 | Content-Type: text/plain; charset=utf-8
6 | Host: HOST
7 |
8 | [response]
9 | HTTP/1.1 200 OK
10 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
11 | Content-type: text/plain; charset=iso-8859-1
12 | Content-Length: 5
13 |
14 | à æ ç
15 |
16 | [test]
17 | (let response = (Darklang.Stdlib.HttpClient.request "get" "http://URL" [] []) |> Builtin.unwrap
18 | response.body) =
19 | "à æ ç"
20 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
4 |
5 | // List of extensions which should be recommended for users of this workspace.
6 | "recommendations": ["ionide.ionide-fsharp", "editorconfig.editorconfig", "dbaeumer.vscode-eslint"],
7 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace.
8 | "unwantedRecommendations": []
9 | }
10 |
--------------------------------------------------------------------------------
/backend/src/LibClientTypes/ClientPusherTypes.fs:
--------------------------------------------------------------------------------
1 | /// Payloads that we send to the client via Pusher.com
2 | module LibClientTypes.Pusher
3 |
4 | open Prelude
5 |
6 | module Payload =
7 | type NewTrace = System.Guid * tlid list
8 |
9 | type New404 = string * string * string * NodaTime.Instant * System.Guid
10 |
11 | // type AddOpV1 = { result : Ops.AddOpResultV1; ``params`` : Ops.AddOpParamsV1 }
12 | //type AddOpV1PayloadTooBig = { tlids : List } // this is so-far unused
13 |
14 | // type UpdateWorkerStates = Map
15 |
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/collections/dtuple.dark:
--------------------------------------------------------------------------------
1 | (1L, 2L) = (1L, 2L)
2 | (1L, 2L, 3L) = (1L, 2L, 3L)
3 | (1L, 2L + 3L, 4L) = (1L, 5L, 4L)
4 |
5 | // note: there is no upper limit set on Tuple size
6 | (1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L) =
7 | (1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L)
8 |
9 | (1L, Builtin.testRuntimeError "test", 3L) =
10 | (Builtin.testDerrorMessage "Uncaught exception: test")
11 |
12 | (1L, Builtin.testRuntimeError "error1", Builtin.testRuntimeError "error2") =
13 | (Builtin.testDerrorMessage "Uncaught exception: error1")
--------------------------------------------------------------------------------
/scripts/run-local-exec:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | PUBLISHED=false
7 |
8 | for i in "$@"
9 | do
10 | case "${i}" in
11 | --published)
12 | PUBLISHED=true
13 | ;;
14 | *) ARGS+=("${i}");;
15 | esac
16 | done
17 |
18 | if [[ "$PUBLISHED" == "true" ]]; then
19 | EXE="backend/Build/out/LocalExec/Release/net8.0/linux-x64/LocalExec"
20 | else
21 | EXE="backend/Build/out/LocalExec/Debug/net8.0/LocalExec"
22 | fi
23 |
24 | "${EXE}" "${ARGS[@]}"
25 |
--------------------------------------------------------------------------------
/backend/src/Prelude/ResizeArray.fs:
--------------------------------------------------------------------------------
1 | module ResizeArray
2 |
3 | type T<'v> = ResizeArray<'v>
4 | let empty () = T()
5 |
6 | let iter (f : 'v -> unit) (l : T<'v>) : unit =
7 | FSharpx.Collections.ResizeArray.iter f l
8 |
9 | let map (f : 'v -> 'v2) (l : T<'v>) : T<'v2> =
10 | FSharpx.Collections.ResizeArray.map f l
11 |
12 | let append (v : 'v) (list : T<'v>) : unit = list.Add(v)
13 |
14 | let toList (l : T<'v>) : List<'v> = FSharpx.Collections.ResizeArray.toList l
15 |
16 | let toSeq (l : T<'v>) : seq<'v> = FSharpx.Collections.ResizeArray.toSeq l
17 |
--------------------------------------------------------------------------------
/packages/darklang/languageServerProtocol/window/telemetry.dark:
--------------------------------------------------------------------------------
1 | // Server->Client notification to log telemetry data
2 |
3 | (*
4 | /// The telemetry event notification is sent from the server to the client to ask
5 | /// the client to log telemetry data.
6 | export namespace TelemetryEventNotification {
7 | export const method: 'telemetry/event' = 'telemetry/event';
8 | export const messageDirection: MessageDirection = MessageDirection.serverToClient;
9 | export const type = new ProtocolNotificationType(method);
10 | }
11 | *)
--------------------------------------------------------------------------------
/vscode-extension/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "darklang-lsp-client",
3 | "description": "Client part of an LSP-powered VS Code extension for Darklang",
4 | "author": "darklang",
5 | "version": "0.0.1",
6 | "publisher": "darklang",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/darklang/dark"
10 | },
11 | "engines": {
12 | "vscode": "^1.63.0"
13 | },
14 | "dependencies": {
15 | "vscode-languageclient": "^7.0.0"
16 | },
17 | "devDependencies": {
18 | "@types/vscode": "^1.63.0"
19 | }
20 | }
--------------------------------------------------------------------------------
/backend/testfiles/httpclient/v0/todo/response-content-encoding-invalid.test:
--------------------------------------------------------------------------------
1 | [expected-request]
2 | GET PATH HTTP/1.1
3 | Accept: */*
4 | Accept-Encoding: deflate, gzip, br
5 | Content-Type: text/plain; charset=utf-8
6 | Host: HOST
7 |
8 |
9 | [response]
10 | HTTP/1.1 200 OK
11 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
12 | Content-type: text/plain; charset=utf-8
13 | Content-Encoding: not-valid
14 |
15 | "Hello back"
16 |
17 | [test]
18 | Darklang.Stdlib.HttpClient.request "get" "http://URL/" [] [] = Error "Unrecognized or bad HTTP Content or Transfer-Encoding"
19 |
--------------------------------------------------------------------------------
/scripts/build/regenerate-test-files:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 |
7 | jsonfile=backend/serialization/oplist-format-latest.json
8 | binfile=backend/serialization/oplist-format-latest.bin
9 |
10 | echo "Before: "
11 | sha1sum "$jsonfile"
12 | sha1sum "$binfile"
13 |
14 | echo -e "\n\nRegenerating: "
15 | cd backend
16 | Build/out/Tests/Debug/net8.0/linux-x64/Tests --regenerate-test-files
17 | cd ..
18 |
19 | echo -e "\n\nAfter: "
20 | sha1sum "$jsonfile"
21 | sha1sum "$binfile"
22 |
--------------------------------------------------------------------------------
/vscode-extension/static/logo-dark-transparent.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/backend/src/LibTreeSitter/Helpers.fs:
--------------------------------------------------------------------------------
1 | []
2 | module LibTreeSitter.Helpers
3 |
4 | open System
5 | open System.IO
6 | open System.Reflection
7 | open System.Runtime.InteropServices
8 |
9 | let baseTempPath = Path.Combine(Path.GetTempPath(), "darklang")
10 |
11 | let resourceExtensionForOS =
12 | if RuntimeInformation.IsOSPlatform(OSPlatform.Windows) then ".dll"
13 | elif RuntimeInformation.IsOSPlatform(OSPlatform.Linux) then ".so"
14 | elif RuntimeInformation.IsOSPlatform(OSPlatform.OSX) then ".dylib"
15 | else raise (PlatformNotSupportedException())
16 |
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/query-string.test:
--------------------------------------------------------------------------------
1 | [http-handler GET /]
2 | Darklang.Stdlib.Http.response (request.url |> Darklang.Stdlib.String.toBytes) 200L
3 |
4 | [request]
5 | GET /?key=value HTTP/1.1
6 | Host: HOST
7 | Date: Sun, 08 Nov 2020 15:38:01 GMT
8 | Content-Length: 7
9 |
10 | ignored
11 |
12 | [response]
13 | HTTP/1.1 200 OK
14 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
15 | x-darklang-execution-id: 0123456789
16 | Server: darklang
17 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
18 | Content-Length: LENGTH
19 |
20 | http://HOST/?key=value
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/url-http.test:
--------------------------------------------------------------------------------
1 | [http-handler GET /a]
2 | Darklang.Stdlib.Http.response (Darklang.Stdlib.String.toBytes request.url) 200L
3 |
4 | [request]
5 | GET /a HTTP/1.1
6 | Host: HOST
7 | Date: Sun, 08 Nov 2020 15:38:01 GMT
8 | Content-Length: 0
9 | X-Forwarded-Proto: http
10 |
11 |
12 |
13 | [response]
14 | HTTP/1.1 200 OK
15 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
16 | x-darklang-execution-id: 0123456789
17 | Server: darklang
18 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
19 | Content-Length: LENGTH
20 |
21 | http://HOST/a
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/url-https.test:
--------------------------------------------------------------------------------
1 | [http-handler GET /a]
2 | Darklang.Stdlib.Http.response (Darklang.Stdlib.String.toBytes request.url) 200L
3 |
4 | [request]
5 | GET /a HTTP/1.1
6 | Host: HOST
7 | Date: Sun, 08 Nov 2020 15:38:01 GMT
8 | Content-Length: 0
9 | X-Forwarded-Proto: https
10 |
11 |
12 |
13 | [response]
14 | HTTP/1.1 200 OK
15 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
16 | x-darklang-execution-id: 0123456789
17 | Server: darklang
18 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
19 | Content-Length: LENGTH
20 |
21 | https://DOMAIN/a
--------------------------------------------------------------------------------
/packages/darklang/stdlib/uuid.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib.Uuid
2 |
3 |
4 | type ParseError = | BadFormat
5 |
6 | /// Generate a new v4 according to RFC 4122
7 | let generate () : Uuid = Builtin.uuidGenerate ()
8 |
9 |
10 | /// Parse a of form {{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}}
11 | let parse (uuid: String) : Stdlib.Result.Result =
12 | Builtin.uuidParse uuid
13 |
14 |
15 | /// Stringify to the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
16 | let toString (uuid: Uuid) : String = Builtin.uuidToString uuid
--------------------------------------------------------------------------------
/backend/src/Prelude/Tuple2.fs:
--------------------------------------------------------------------------------
1 | module Tuple2
2 |
3 | let fromKeyValuePair
4 | (kvp : System.Collections.Generic.KeyValuePair<'a, 'b>)
5 | : ('a * 'b) =
6 | kvp.Key, kvp.Value
7 |
8 | let toKeyValuePair
9 | ((k, v) : 'a * 'b)
10 | : (System.Collections.Generic.KeyValuePair<'a, 'b>) =
11 | System.Collections.Generic.KeyValuePair<'a, 'b>(k, v)
12 |
13 | let first (v1 : 'a, _ : 'b) : 'a = v1
14 | let second (_ : 'a, v2 : 'b) : 'b = v2
15 | let mapFirst (f : 'x -> 'r) (x : 'x, y : 'y) : 'r * 'y = (f x, y)
16 | let mapSecond (f : 'y -> 'r) (x : 'x, y : 'y) : 'x * 'r = (x, f y)
17 |
--------------------------------------------------------------------------------
/packages/darklang/languageServerProtocol/lifecycle/shutdown.dark:
--------------------------------------------------------------------------------
1 | (*
2 | /// A shutdown request is sent from the client to the server.
3 | /// It is sent once when the client decides to shutdown the
4 | /// server. The only notification that is sent after a shutdown request
5 | /// is the exit event.
6 | export namespace ShutdownRequest {
7 | export const method: 'shutdown' = 'shutdown';
8 | export const messageDirection: MessageDirection = MessageDirection.clientToServer;
9 | export const type = new ProtocolRequestType0(method);
10 | }
11 | *)
--------------------------------------------------------------------------------
/scripts/production/gcp-get-logs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 |
4 | gcloud logging read \
5 | --freshness=1m \
6 | --flatten=jsonPayload.data \
7 | --order=asc \
8 | | grep -v '\-\-\-' \
9 | | sed "s/^ \'//" \
10 | | sed "s/'$//" \
11 | | sed 's/\\e\[6;30m//g' \
12 | | sed 's/\\e\[0m//g' \
13 | | sed 's/e\[0m//g' \
14 | | sed 's/\\e\[6;31m//g' \
15 | | sed 's/\\\\\\n//g' \
16 | | sed 's/\\\\n//g' \
17 | | sed 's/\\n//g' \
18 | | sed 's/\\\\\\//g' \
19 | | sed 's/\\\\//g' \
20 | | sed 's/\\//g' \
21 | | sed 's/log"/log/' \
22 | | sed 's/"log/log/'
23 |
24 |
--------------------------------------------------------------------------------
/vscode-extension/static/logo-dark-transparent-low-margin.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/scripts/devcontainer/_vscode-post-start-command:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | echo "Fetching and building tree-sitter library"
6 | ./scripts/build/build-tree-sitter.sh
7 |
8 | echo "Starting build server"
9 |
10 | mkdir -p rundir/logs/
11 |
12 | git config --global --add safe.directory /home/dark/app
13 |
14 | nohup ./scripts/build/_build-server --compile --watch &> /home/dark/app/rundir/logs/build-server.log &
15 |
16 | # It seems that if we don't sleep here, the server does not start properly in all cases
17 | sleep 2
18 |
19 | echo "Build server started"
20 |
--------------------------------------------------------------------------------
/tree-sitter-darklang/test/corpus/exhaustive/exprs/floats.txt:
--------------------------------------------------------------------------------
1 | ==================
2 | float literal
3 | ==================
4 |
5 | 1.0
6 |
7 | ---
8 |
9 | (source_file (expression (simple_expression (float_literal))))
10 |
11 |
12 | ==================
13 | float literal (negative)
14 | ==================
15 |
16 | -1.0
17 |
18 | ---
19 | (source_file (expression (simple_expression (float_literal))))
20 |
21 |
22 | ==================
23 | float literal (zero)
24 | ==================
25 |
26 | -00000000.000
27 |
28 | ---
29 | (source_file (expression (simple_expression (float_literal))))
--------------------------------------------------------------------------------
/vscode-extension/.vscodeignore:
--------------------------------------------------------------------------------
1 | .vscode/**
2 | **/*.ts
3 | **/*.map
4 | .gitignore
5 | **/tsconfig.json
6 | **/tsconfig.base.json
7 | .travis.yml
8 | client/node_modules/**
9 | !client/node_modules/vscode-jsonrpc/**
10 | !client/node_modules/vscode-languageclient/**
11 | !client/node_modules/vscode-languageserver-protocol/**
12 | !client/node_modules/vscode-languageserver-types/**
13 | !client/node_modules/{minimatch,brace-expansion,concat-map,balanced-match}/**
14 | !client/node_modules/{semver,lru-cache,yallist}/**
15 | # TODO figure out what's adding the .mono directory
16 | .mono
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 |
4 | - package-ecosystem: docker
5 | directory: "/"
6 | schedule:
7 | interval: daily
8 | open-pull-requests-limit: 10
9 |
10 | - package-ecosystem: npm
11 | directory: "/"
12 | schedule:
13 | interval: daily
14 | open-pull-requests-limit: 10
15 |
16 | - package-ecosystem: nuget
17 | directory: "/backend"
18 | schedule:
19 | interval: daily
20 | open-pull-requests-limit: 10
21 |
22 | - package-ecosystem: terraform
23 | directory: "/tf"
24 | schedule:
25 | interval: daily
26 | open-pull-requests-limit: 10
27 |
--------------------------------------------------------------------------------
/backend/src/LibClientTypes/README.md:
--------------------------------------------------------------------------------
1 | # LibClientTypes
2 |
3 | Maintains types used to communicate with the `client`/editor:
4 |
5 | - API request/response payloads
6 | - requests/responses used in Analysis via WebAssembly-compiled code
7 | - Pusher.com payloads
8 | - data injected into `ui.html`
9 |
10 | This project intentionally has no dependencies on other Dark projects (other than
11 | Prelude), to sensure no internal domain types are referenced.
12 |
13 | Translation between these types and "domain types" is provided via separate
14 | `ClientTypes2___Types` projects.
15 |
16 | ## Note
17 |
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/injected-icon-post-roundtrip.test:
--------------------------------------------------------------------------------
1 | [http-handler POST /]
2 | Darklang.Stdlib.Http.response request.body 200L
3 |
4 | [request]
5 | POST / HTTP/1.1
6 | Host: HOST
7 | Date: Sun, 08 Nov 2020 15:38:01 GMT
8 | Content-Length: 454
9 |
10 |
11 |
12 | [response]
13 | HTTP/1.1 200 OK
14 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
15 | x-darklang-execution-id: 0123456789
16 | Server: darklang
17 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
18 | Content-Length: 454
19 |
20 |
--------------------------------------------------------------------------------
/tf/vpc.tf:
--------------------------------------------------------------------------------
1 |
2 | resource "google_compute_network" "default" {
3 | name = "default"
4 | description = "Default network for the project"
5 | auto_create_subnetworks = "true"
6 | }
7 |
8 | resource "google_vpc_access_connector" "serverless_connector_1" {
9 | name = "serverless-connector-1"
10 | network = google_compute_network.default.id
11 | region = "us-central1"
12 | ip_cidr_range = "10.8.100.0/28"
13 | max_instances = 10
14 | min_instances = 2
15 | max_throughput = 1000
16 | machine_type = "e2-micro"
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/containers/queueworker/Dockerfile:
--------------------------------------------------------------------------------
1 | # Dockerfile for the processing the event queue
2 |
3 | FROM dark-fsharp-service:latest
4 |
5 | WORKDIR /home/dark
6 |
7 | COPY --chown=dark:dark scripts scripts
8 |
9 | RUN mkdir app
10 |
11 | # Setting this now means we can set the filesystem to readonly
12 | ENV DARK_CONFIG_RUNDIR=/home/dark/gcp-rundir
13 | RUN ./scripts/devcontainer/_create-app-directories
14 |
15 | COPY --chown=dark:dark backend/Build/out/QueueWorker/Release/net8.0/linux-x64/publish/QueueWorker app/
16 | RUN ./scripts/linting/_check-linked-libs app/QueueWorker
17 |
18 | CMD ./app/QueueWorker
19 |
--------------------------------------------------------------------------------
/scripts/deployment/_deploy-lock-request:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # Make requests to deploy lock server
5 |
6 | set -euo pipefail
7 |
8 | if [ ! -v DEPLOY_LOCK_TOKEN ] ;
9 | then
10 | echo "No deploy lock token, get it from https://darklang.com/a/ops-circleci" >&2
11 | exit 1
12 | fi
13 |
14 | REQUEST_PATH=$1
15 | METHOD=$2
16 |
17 | curl -f -s "https://ops-circleci.builtwithdark.com/deploy-lock${REQUEST_PATH}" \
18 | -X "${METHOD}" \
19 | -H 'Content-type: application/json' \
20 | -H "Authorization: Bearer ${DEPLOY_LOCK_TOKEN}"
21 |
--------------------------------------------------------------------------------
/backend/src/BuiltinCli/Builtin.fs:
--------------------------------------------------------------------------------
1 | module BuiltinCli.Builtin
2 |
3 | module Builtin = LibExecution.Builtin
4 |
5 | let fnRenames : Builtin.FnRenames =
6 | // old names, new names
7 | // eg: fn "Http" "respond" 0, fn "Http" "response" 0
8 | []
9 |
10 | let builtins =
11 | Builtin.combine
12 | [ Libs.Directory.builtins
13 | Libs.Environment.builtins
14 | Libs.File.builtins
15 | Libs.Execution.builtins
16 | Libs.Output.builtins
17 | Libs.Process.builtins
18 | Libs.Stdin.builtins
19 | Libs.Time.builtins
20 | Libs.Terminal.builtins ]
21 | fnRenames
22 |
--------------------------------------------------------------------------------
/packages/darklang/cli/installation/version.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Cli.Installation.Version
2 |
3 |
4 | let execute (state: AppState) (args: List) : AppState =
5 | let versionInfo = Helpers.getVersionInfo ()
6 | Stdlib.printLine versionInfo
7 | state
8 |
9 |
10 | let complete (state: AppState) (args: List) : List =
11 | []
12 |
13 |
14 | let help (_state: AppState) : Unit =
15 | [
16 | "Usage: version"
17 | "Display CLI version and installation information."
18 | ""
19 | "Shows current version, installation mode, and location."
20 | ] |> Stdlib.printLines
21 |
--------------------------------------------------------------------------------
/packages/darklang/stdlib/alt-json.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Stdlib.AltJson
2 |
3 |
4 | type Json =
5 | | Null
6 | | Bool of Bool
7 | | Number of Float
8 | | String of String
9 | | Array of List
10 | | Object of List<(String * Json)>
11 |
12 |
13 | module ParseError =
14 | type ParseError = | NotJson
15 |
16 | let toString (e: ParseError) : String =
17 | match e with
18 | | NotJson -> "Not JSON"
19 |
20 |
21 | let format (j: Json) : String = Builtin.altJsonFormat j
22 |
23 | let parse (jsonString: String) : Result.Result =
24 | Builtin.altJsonParse jsonString
--------------------------------------------------------------------------------
/scripts/formatting/pre-commit-hook.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | # To install:
7 | # - cp scripts/formatting/pre-commit-hook.sh .git/hooks/pre-commit
8 | # - chmod +x .git/hooks/pre-commit
9 |
10 | # Works on all filetype, silently ignoring unsupported files
11 |
12 | files=$(git diff --cached --name-only --diff-filter=ACM)
13 |
14 | # format all staged files
15 | echo "$files" | xargs scripts/formatting/format check --quiet
16 | # Add back the modified/formatted files to staging
17 | echo "$files" | xargs git add
18 |
19 | exit 0
20 |
--------------------------------------------------------------------------------
/backend/src/Cli/README.md:
--------------------------------------------------------------------------------
1 | # `darklang` CLI executable
2 |
3 | This is a project that yields a `darklang` executable artifact.
4 | It builds to many platforms -- see the .fsproj file for details.
5 |
6 | ## Usage
7 |
8 | - create script with `#!/usr/bin/env darklang`
9 | - runs same as if it was bash
10 |
11 | ## Structure
12 |
13 | - `Cli`
14 | - binary that runs dark code
15 | - supported greatly by `LibCli`
16 | - `LibCli`
17 | - stdlib fns and types for filesystem and other posix stuff
18 | - print to stdout (and stderr?)
19 | - read stdin (start processing once it closes)
20 | - `Directory.\*`
21 | - `File.\*`
--------------------------------------------------------------------------------
/packages/darklang/languageServerProtocol/lifecycle/initialized.dark:
--------------------------------------------------------------------------------
1 | (*
2 | export interface InitializedParams {}
3 |
4 | /// The initialized notification is sent from the client to the
5 | /// server after the client is fully initialized and the server
6 | /// is allowed to send requests from the server to the client.
7 | export namespace InitializedNotification {
8 | export const method: 'initialized' = 'initialized';
9 | export const messageDirection: MessageDirection = MessageDirection.clientToServer;
10 | export const type = new ProtocolNotificationType(method);
11 | }
12 | *)
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/apply/einfix.dark:
--------------------------------------------------------------------------------
1 | 5L + 3L = 8L
2 | "xx" ++ "yy" = "xxyy"
3 | (5L + (3L)) = 8L
4 | Stdlib.Int64.add_v0 5L 3L = 8L
5 |
6 | 5L + true =
7 | Builtin.testDerrorMessage "Builtin.int64Add's 2nd parameter `b` expects Int64, but got Bool (true)"
8 |
9 | 5L + (Builtin.testRuntimeError "error") =
10 | Builtin.testDerrorMessage "Uncaught exception: error"
11 |
12 | (Builtin.testRuntimeError "error") + 5L =
13 | Builtin.testDerrorMessage "Uncaught exception: error"
14 |
15 | (Builtin.testRuntimeError "one") + (Builtin.testRuntimeError "two") =
16 | Builtin.testDerrorMessage "Uncaught exception: one"
--------------------------------------------------------------------------------
/containers/cronchecker/Dockerfile:
--------------------------------------------------------------------------------
1 | # Dockerfile for the service checking crons and loading them into the event queue
2 |
3 | FROM dark-fsharp-service:latest
4 |
5 | WORKDIR /home/dark
6 |
7 | COPY --chown=dark:dark scripts scripts
8 |
9 | RUN mkdir app
10 |
11 | # Setting this now means we can set the filesystem to readonly
12 | ENV DARK_CONFIG_RUNDIR=/home/dark/gcp-rundir
13 | RUN ./scripts/devcontainer/_create-app-directories
14 |
15 | COPY --chown=dark:dark backend/Build/out/CronChecker/Release/net8.0/linux-x64/publish/CronChecker app/
16 |
17 | RUN ./scripts/linting/_check-linked-libs app/CronChecker
18 |
19 | CMD ./app/CronChecker
--------------------------------------------------------------------------------
/tf/custom-domains.tf:
--------------------------------------------------------------------------------
1 |
2 | resource "google_certificate_manager_certificate_map_entry" "packages-darklang-com" {
3 | name = "packages-darklang-com-entry"
4 | description = ""
5 | map = google_certificate_manager_certificate_map.bwdserver.name
6 | certificates = [google_certificate_manager_certificate.packages-darklang-com.id]
7 | hostname = "packages.darklang.com"
8 | }
9 |
10 | resource "google_certificate_manager_certificate" "packages-darklang-com" {
11 | name = "packages-darklang-com"
12 | description = ""
13 | managed {
14 | domains = ["packages.darklang.com"]
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/backend/testfiles/httpclient/v0/_request-content-type-invalid.test:
--------------------------------------------------------------------------------
1 | [expected-request]
2 | GET PATH HTTP/1.1
3 | Accept: */*
4 | Accept-Encoding: deflate, gzip, br
5 | Content-Type: just an invalid string
6 | Host: HOST
7 |
8 | [response]
9 | HTTP/1.1 200 OK
10 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
11 | Content-type: text/plain; charset=utf-8
12 | Content-Length: LENGTH
13 |
14 | "Hello back"
15 |
16 | [test]
17 | (let reqHeaders = [("Content-Type", "just an invalid string")]
18 | let response = Darklang.Stdlib.HttpClient.request "get" "http://URL" reqHeaders []
19 | response) ==
20 | Builtin.Test.runtimeError "Invalid content-type header"
21 |
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/simple-inline-string-post.test:
--------------------------------------------------------------------------------
1 | [http-handler POST /]
2 | (let body = (request.body |> Darklang.Stdlib.List.length |> Darklang.Stdlib.Int64.toString |> Darklang.Stdlib.String.toBytes)
3 | Darklang.Stdlib.Http.response body 200L)
4 |
5 | [request]
6 | POST / HTTP/1.1
7 | Host: HOST
8 | Date: Sun, 08 Nov 2020 15:38:01 GMT
9 | Content-Length: 13
10 |
11 | 13 characters
12 |
13 | [response]
14 | HTTP/1.1 200 OK
15 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
16 | x-darklang-execution-id: 0123456789
17 | Server: darklang
18 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
19 | Content-Length: 2
20 |
21 | 13
--------------------------------------------------------------------------------
/docs/production/auditlogs.md:
--------------------------------------------------------------------------------
1 | # Audit logs
2 |
3 | We now have Cloud Audit Logs turned on for our storage buckets. To see these
4 | logs, go to https://console.cloud.google.com/logs/viewer and select "GCS Bucket"
5 | from the resource dropdown. You can also further drill down to a specific
6 | bucket.
7 |
8 | For more details on why we picked this approach and not access logs, or for
9 | links to docs on exporting these logs to another bucket (for analysis outside of
10 | GCloud), see
11 | https://www.notion.so/darklang/Cloud-Storage-Logs-5a686f3d235f47f395f68a75a1e2c794 .
12 |
13 | Tags for search:
14 | audit log auditlog security storage bucket backups
15 |
--------------------------------------------------------------------------------
/scripts/deployment/_notify-deployment-rollbar:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | # Tell rollbar about a deploy
7 |
8 | LOCAL_USERNAME="$(grep 'account' ~/.config/gcloud/configurations/config_default | awk '{print $3}' | awk -F "@" '{print $1}')"
9 |
10 | curl -s https://api.rollbar.com/api/1/deploy/ \
11 | -F "access_token=${DARK_CONFIG_ROLLBAR_POST_SERVER_ITEM}" \
12 | -F "environment=production" \
13 | -F "revision=$(git rev-parse --short HEAD)" \
14 | -F "comment=$1" \
15 | -F "local_username=${LOCAL_USERNAME}" > /dev/null
16 | echo "Rollbar notified."
17 |
18 |
--------------------------------------------------------------------------------
/backend/src/BuiltinPM/Builtin.fs:
--------------------------------------------------------------------------------
1 | module BuiltinPM.Builtin
2 |
3 | open Prelude
4 | open LibExecution.RuntimeTypes
5 |
6 | module Builtin = LibExecution.Builtin
7 | module PT = LibExecution.ProgramTypes
8 |
9 |
10 | let fnRenames : Builtin.FnRenames =
11 | // old names, new names
12 | // eg: fn "Http" "respond" 0, fn "Http" "response" 0
13 | []
14 |
15 | let builtins (pm : PT.PackageManager) : Builtins =
16 | Builtin.combine
17 | [ Libs.Packages.builtins pm
18 | Libs.PackageOps.builtins
19 | Libs.Instances.builtins
20 | Libs.Branches.builtins
21 | Libs.Sync.builtins
22 | Libs.Scripts.builtins ]
23 | fnRenames
24 |
--------------------------------------------------------------------------------
/backend/src/LibBinarySerialization/Serializers/RT/PackageValue.fs:
--------------------------------------------------------------------------------
1 | module LibBinarySerialization.Serializers.RT.PackageValue
2 |
3 | open System
4 | open System.IO
5 | open Prelude
6 |
7 | open LibExecution.RuntimeTypes
8 |
9 | open LibBinarySerialization.BinaryFormat
10 | open LibBinarySerialization.Serializers.Common
11 | open LibBinarySerialization.Serializers.RT.Common
12 |
13 | let write (w : BinaryWriter) (c : PackageValue.PackageValue) : unit =
14 | Guid.write w c.id
15 | Dval.write w c.body
16 |
17 | let read (r : BinaryReader) : PackageValue.PackageValue =
18 | let id = Guid.read r
19 | let body = Dval.read r
20 | { id = id; body = body }
21 |
--------------------------------------------------------------------------------
/backend/src/LibService/Init.fs:
--------------------------------------------------------------------------------
1 | module LibService.Init
2 |
3 | open Prelude
4 |
5 | let init (serviceName : string) : unit =
6 | printTime $"Initing LibService in {serviceName}"
7 | Rollbar.init serviceName
8 | Telemetry.init serviceName
9 | printTime $" Inited LibService in {serviceName}"
10 |
11 |
12 | /// Called when shutting down cloud services. Used to explicitly flush any buffered
13 | /// connections for LaunchDarkly.
14 | let shutdown (serviceName : string) : unit =
15 | printTime $"Shutting down LibService in {serviceName}"
16 | LaunchDarkly.flush ()
17 | Telemetry.flush ()
18 | printTime $"Shutting down LibService in {serviceName}"
19 |
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/response-with-500.test:
--------------------------------------------------------------------------------
1 | [http-handler POST /]
2 | (let body = (request.body |> Darklang.Stdlib.List.length |> Darklang.Stdlib.Int64.toString |> Darklang.Stdlib.String.toBytes)
3 | Darklang.Stdlib.Http.response body 500L)
4 |
5 | [request]
6 | POST / HTTP/1.1
7 | Host: HOST
8 | Date: Sun, 08 Nov 2020 15:38:01 GMT
9 | Content-Length: 13
10 |
11 | 13 characters
12 |
13 | [response]
14 | HTTP/1.1 500 Internal Server Error
15 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
16 | x-darklang-execution-id: 0123456789
17 | Server: darklang
18 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
19 | Content-Length: 2
20 |
21 | 13
--------------------------------------------------------------------------------
/scripts/linting/yamllinter:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | all_yaml_files() {
7 | find ./* -type f \
8 | \( -name "*.yml" \
9 | -o -name "*.yaml" \) -print \
10 | -o -path ".git" -prune \
11 | -o -path "rundir" -prune \
12 | -o -path "./rundir" -prune \
13 | -o -path "backend/paket-files" -prune \
14 | -o -path "./backend/paket-files" -prune \
15 | -o -path ".circleci/config.yml" -prune
16 | }
17 |
18 | if [[ "$#" -eq 1 ]]; then
19 | yamllint "$1"
20 | else
21 | echo "linting yaml files ..."
22 | all_yaml_files | xargs yamllint
23 | fi
24 |
--------------------------------------------------------------------------------
/tree-sitter-darklang/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tree-sitter-darklang"
3 | description = "darklang grammar for the tree-sitter parsing library"
4 | version = "0.0.1"
5 | keywords = ["incremental", "parsing", "darklang"]
6 | categories = ["parsing", "text-editors"]
7 | repository = "https://github.com/darklang/dark"
8 | edition = "2018"
9 | license = "MIT"
10 |
11 | build = "bindings/rust/build.rs"
12 | include = [
13 | "bindings/rust/*",
14 | "grammar.js",
15 | "queries/*",
16 | "src/*",
17 | ]
18 |
19 | [lib]
20 | path = "bindings/rust/lib.rs"
21 |
22 | [dependencies]
23 | tree-sitter = "~0.20.10"
24 |
25 | [build-dependencies]
26 | cc = "1.0"
27 |
--------------------------------------------------------------------------------
/packages/darklang/cli/packages/display.dark:
--------------------------------------------------------------------------------
1 | module Darklang.Cli.Packages.Display
2 |
3 | /// Icon mappings for different entity types
4 | let getIcon (entityType: EntityType) : String =
5 | match entityType with
6 | | Module -> "🗂️"
7 | | Function -> "⚡"
8 | | Type -> "🏷️"
9 | | Value -> "💎"
10 |
11 |
12 | /// Get section header with icon for entity type
13 | let getSectionHeader (entityType: String) : String =
14 | match entityType with
15 | | "module" -> "🗂️ Modules:"
16 | | "function" -> "⚡ Functions:"
17 | | "type" -> "🏷️ Types:"
18 | | "value" -> "💎 Values:"
19 | | "submodule" -> "🗂️ Submodules:"
20 | | _ -> entityType ++ ":"
21 |
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/simple-injected-string-post.test:
--------------------------------------------------------------------------------
1 | [http-handler POST /]
2 | (let body = (request.body |> Darklang.Stdlib.List.length |> Darklang.Stdlib.Int64.toString |> Darklang.Stdlib.String.toBytes)
3 | Darklang.Stdlib.Http.response body 200L)
4 |
5 | [request]
6 | POST / HTTP/1.1
7 | Host: HOST
8 | Date: Sun, 08 Nov 2020 15:38:01 GMT
9 | Content-Length: 11
10 |
11 |
12 |
13 | [response]
14 | HTTP/1.1 200 OK
15 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
16 | x-darklang-execution-id: 0123456789
17 | Server: darklang
18 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
19 | Content-Length: 2
20 |
21 | 11
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/injected-icon-post-length.test:
--------------------------------------------------------------------------------
1 | [http-handler POST /]
2 | (let body = (request.body |> Darklang.Stdlib.List.length |> Darklang.Stdlib.Int64.toString |> Darklang.Stdlib.String.toBytes)
3 | Darklang.Stdlib.Http.response body 200L)
4 |
5 | [request]
6 | POST / HTTP/1.1
7 | Host: HOST
8 | Date: Sun, 08 Nov 2020 15:38:01 GMT
9 | Content-Length: 454
10 |
11 |
12 |
13 | [response]
14 | HTTP/1.1 200 OK
15 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
16 | x-darklang-execution-id: 0123456789
17 | Server: darklang
18 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
19 | Content-Length: 3
20 |
21 | 454
--------------------------------------------------------------------------------
/.circleci/gcp-workload-identity-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "external_account",
3 | "audience": "//iam.googleapis.com/projects/234768451432/locations/global/workloadIdentityPools/circleci/providers/circleci",
4 | "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
5 | "token_url": "https://sts.googleapis.com/v1/token",
6 | "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/circleci-deployer@darklang-next.iam.gserviceaccount.com:generateAccessToken",
7 | "credential_source": {
8 | "file": "/home/dark/app/CIRCLE_OIDC_TOKEN_FILE",
9 | "format": {
10 | "type": "text"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "FSharp.inlayHints.typeAnnotations": false,
3 | "[fsharp]": {
4 | "editor.inlayHints.enabled": "off"
5 | },
6 | "FSharp.inlayHints.parameterNames": false,
7 | "FSharp.workspacePath": "./backend/fsdark.sln",
8 | "files.associations": {
9 | "*.dark": "fsharp"
10 | },
11 | "[vue]": {
12 | "editor.defaultFormatter": "esbenp.prettier-vscode"
13 | },
14 | "[html]": {
15 | "editor.defaultFormatter": "esbenp.prettier-vscode"
16 | },
17 | "[javascript]": {
18 | "editor.defaultFormatter": "esbenp.prettier-vscode"
19 | },
20 | "[typescript]": {
21 | "editor.defaultFormatter": "esbenp.prettier-vscode"
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/backend/testfiles/httpclient/README.md:
--------------------------------------------------------------------------------
1 | # Dark HttpClient test files
2 |
3 | The files in this directory are tests of the `HttpClient::request` standard
4 | library function. The test suite sets up a server that we can make HTTP requests
5 | against, using HttpClient. It then checks the request is as expected, and
6 | returns a response to be parsed by the HTTP client.
7 |
8 | These files are read, parsed, and evaluated by `HttpClient.Tests.fs`.
9 |
10 | ---
11 |
12 | This all works almost exactly how the `HttpClient::` functions are tested, in the
13 | corresponding `httpclient` directory. Please refer to the `README.md` there for
14 | details on how these tests are set up.
15 |
--------------------------------------------------------------------------------
/backend/src/Prelude/Regex.fs:
--------------------------------------------------------------------------------
1 | module Regex
2 |
3 | open System.Text.RegularExpressions
4 |
5 | // Active pattern for regexes
6 | let (|Regex|_|) (pattern : string) (input : string) =
7 | let m = Regex.Match(input, pattern)
8 | if m.Success then Some(List.tail [ for g in m.Groups -> g.Value ]) else None
9 |
10 | let (|RegexAny|_|) (pattern : string) (input : string) =
11 | let options = RegexOptions.Singleline
12 | let m = Regex.Match(input, pattern, options)
13 | if m.Success then Some(List.tail [ for g in m.Groups -> g.Value ]) else None
14 |
15 |
16 | let matches (pattern : string) (input : string) : bool =
17 | let m = Regex.Match(input, pattern)
18 | m.Success
19 |
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/url-custom-domain.test:
--------------------------------------------------------------------------------
1 | [http-handler GET /a]
2 | Darklang.Stdlib.Http.response (Darklang.Stdlib.String.toBytes request.url) 200L
3 |
4 | [domain customdomain.myspecialdomain.com]
5 |
6 | [request]
7 | GET /a HTTP/1.1
8 | Host: customdomain.myspecialdomain.com
9 | Date: Sun, 08 Nov 2020 15:38:01 GMT
10 | Content-Length: 0
11 | X-forwarded-proto: https
12 |
13 |
14 |
15 | [response]
16 | HTTP/1.1 200 OK
17 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
18 | x-darklang-execution-id: 0123456789
19 | Server: darklang
20 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
21 | Content-Length: LENGTH
22 |
23 | https://customdomain.myspecialdomain.com/a
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/x-forwarded-proto-ignored.test:
--------------------------------------------------------------------------------
1 | [http-handler GET /a]
2 | Darklang.Stdlib.Http.response (Darklang.Stdlib.String.toBytes request.url) 200L
3 |
4 |
5 | [domain forwarded.myspecialdomain.com]
6 |
7 | [request]
8 | GET /a HTTP/1.1
9 | Host: forwarded.myspecialdomain.com
10 | Date: Sun, 08 Nov 2020 15:38:01 GMT
11 | Content-Length: 0
12 | X-forwarded-proto: ftp
13 |
14 |
15 |
16 | [response]
17 | HTTP/1.1 200 OK
18 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
19 | x-darklang-execution-id: 0123456789
20 | Server: darklang
21 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
22 | Content-Length: LENGTH
23 |
24 | http://forwarded.myspecialdomain.com/a
--------------------------------------------------------------------------------
/config/local.template:
--------------------------------------------------------------------------------
1 | ######################################
2 | # XXX: Changes won't take effect until you restart script/builder
3 | # or rebuild the vscode dev container
4 | #
5 | # If using a VS Code devcontainer, you need to uncomment out the lines to enable this
6 | ######################################
7 |
8 | # Values set here override the defaults in config/dev (or whatever config is loaded)
9 |
10 | ######################################
11 | # XXX: Changes won't take effect until you restart script/builder
12 | # or rebuild the vscode dev container
13 | #
14 | # If using a VS Code devcontainer, you need to uncomment out the lines to enable this
15 | ######################################
--------------------------------------------------------------------------------
/scripts/deployment/new-deploy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | set -x
7 |
8 | # Read each entry from the JSON file and deploy the container
9 | jq -c '.[]' image-digests.json | while IFS= read -r line; do
10 | container=$(echo "$line" | jq -r '.name')
11 | image=$(echo "$line" | jq -r '.digest')
12 |
13 | # ProdExec is only deployed on demand
14 | if [[ "$container" == "prodexec" ]]; then
15 | continue
16 | fi
17 |
18 | gcloud run services update "$container" \
19 | --project darklang-next \
20 | --region us-central1 \
21 | --image "$image"
22 | done
23 |
24 |
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/interpreter.dark:
--------------------------------------------------------------------------------
1 | // Tests that don't quite fit in the other files,
2 | // and are more focused on interpreter behavior.
3 |
4 |
5 | // This test used to cause a stack overflow, but now passes everywhere.
6 | // Let's keep this around to ensure we never regress.
7 | ((Stdlib.List.repeat_v0 348L 1L)
8 | |> Builtin.unwrap
9 | |> Stdlib.List.map (fun _f -> 1)
10 | |> Stdlib.List.length) = 348L
11 |
12 | // Just to show off, let's increase the size of the list
13 | // (CLEANUP include this -- it's just a bit slow right now.)
14 | // ((Stdlib.List.repeat_v0 3480L 1L)
15 | // |> Builtin.unwrap
16 | // |> Stdlib.List.map (fun _f -> 1)
17 | // |> Stdlib.List.length) = 3480L
--------------------------------------------------------------------------------
/packages/darklang/scm/branch.dark:
--------------------------------------------------------------------------------
1 | module Darklang.SCM.Branch
2 |
3 | type Branch =
4 | { id: Uuid
5 | name: String
6 | createdAt: DateTime
7 | mergedAt: Stdlib.Option.Option }
8 |
9 |
10 | /// List all branches
11 | let list () : List = Builtin.scmBranchList ()
12 |
13 | /// Get a specific branch by ID
14 | let get (branchID: Uuid) : Stdlib.Option.Option =
15 | Builtin.scmBranchGet branchID
16 |
17 | /// Find branches by name (may return multiple if names collide)
18 | let findByName (name: String) : List =
19 | Builtin.scmBranchFindByName name
20 |
21 | /// Create a new branch
22 | let create (name: String) : Branch =
23 | Builtin.scmBranchCreate name
24 |
--------------------------------------------------------------------------------
/backend/src/LibExecution/DarkDateTime.fs:
--------------------------------------------------------------------------------
1 | module LibExecution.DarkDateTime
2 |
3 | open NodaTime
4 |
5 | open Prelude
6 |
7 | // A datetime in Dark is always in UTC, so we don't include the utc info
8 | type T = LocalDateTime
9 | let utc = DateTimeZone.Utc
10 |
11 | let toZonedDateTime (dt : T) = ZonedDateTime(dt, utc, Offset.Zero)
12 |
13 | let toInstant (dt : T) = (toZonedDateTime dt).ToInstant()
14 |
15 | let toDateTimeUtc (dt : T) = (toInstant dt).ToDateTimeUtc()
16 |
17 | let fromInstant (i : Instant) : T = i.toUtcLocalTimeZone ()
18 |
19 | let fromDateTime (dt : System.DateTime) : T =
20 | Instant.FromDateTimeUtc dt |> fromInstant
21 |
22 | let toIsoString (d : T) : string = (toInstant d).toIsoString ()
23 |
--------------------------------------------------------------------------------
/vscode-extension/README.md:
--------------------------------------------------------------------------------
1 | # Darklang VS Code Extension
2 |
3 | This is a work-in-progress, not yet ready for general consumption.
4 |
5 | Join [our Discord](https://darklang.com/discord-invite) to learn more.
6 |
7 | ## Running it
8 |
9 | - (run whole repo in devcontainer -- see root README)
10 | - `cd` to this dir
11 | - `npm i`
12 | - hit F5
13 |
14 | ## Publishing
15 |
16 | The extension is automatically published to the VS Code Marketplace when:
17 |
18 | 1. The version in [`package.json`](./package.json) is bumped
19 | 2. The change is merged to the `main` branch
20 |
21 | The CI pipeline compares the package.json version with the marketplace version and only publishes if the package.json version is newer.
22 |
--------------------------------------------------------------------------------
/scripts/build/_dotnet-wrapper:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | # note: no set -e
5 | set -uo pipefail
6 | set +e
7 |
8 | # run the last segment of a pipeline in the current shell. This allows getting
9 | # the exit code.
10 | shopt -s lastpipe
11 |
12 | cd backend && dotnet "$@" 2>&1 | while read -r line; do
13 | # this error consistently breaks our compile in the build script
14 | if [[ "$line" == *"warning MSB3026: Could not copy "* ]]; then
15 | echo "Saw a failed copy, killing servers"
16 | killall BwdServer || true
17 | killall CronChecker || true
18 | killall QueueWorker || true
19 | killall Tests || true
20 | fi
21 | echo "$line"
22 | done
--------------------------------------------------------------------------------
/backend/src/LibService/Kestrel.fs:
--------------------------------------------------------------------------------
1 | module LibService.Kestrel
2 |
3 | open Prelude
4 |
5 | type KestrelServerOptions =
6 | Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions
7 |
8 | // Apply some simple options so things don't get out of control
9 | let configureKestrel (opts : KestrelServerOptions) : unit =
10 | opts.Limits.MaxConcurrentConnections <- 1000L
11 | opts.Limits.MaxConcurrentUpgradedConnections <- 0L // don't support websockets
12 | opts.Limits.MaxRequestBodySize <- 10L * 1024L * 1024L // 10MB
13 | opts.Limits.RequestHeadersTimeout <- System.TimeSpan.FromSeconds 10.0
14 | opts.AllowSynchronousIO <- false // prevent deadlock of some kind
15 | opts.AddServerHeader <- false // Don't add kestrel
16 |
--------------------------------------------------------------------------------
/packages/darklang/languageServerProtocol/tracing.dark:
--------------------------------------------------------------------------------
1 | // Supports:
2 | // - the client setting a trace level
3 | // - the server logging a trace
4 |
5 | (*
6 | namespace SetTraceNotification {
7 | export const method: '$/setTrace' = '$/setTrace';
8 | export const messageDirection: MessageDirection = MessageDirection.clientToServer;
9 | export const type = new ProtocolNotificationType(method);
10 | }
11 |
12 | namespace LogTraceNotification {
13 | export const method: '$/logTrace' = '$/logTrace';
14 | export const messageDirection: MessageDirection = MessageDirection.serverToClient;
15 | export const type = new ProtocolNotificationType(method);
16 | }
17 | *)
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/custom-data/record-field-acess.dark:
--------------------------------------------------------------------------------
1 | type MyRecord = { col1: Int64 }
2 |
3 | (let x = MyRecord { col1 = 1L } in x.col1) = 1L
4 |
5 | module Errors =
6 | (let x = MyRecord { col1 = 1L } in x.___) =
7 | (Builtin.testDerrorMessage "Field name is empty")
8 |
9 | (let x = MyRecord { col1 = 1L } in x.fieldName) =
10 | (Builtin.testDerrorMessage "Tried to access field `fieldName`, but it doesn't exist")
11 |
12 | (Builtin.testRuntimeError "error").fieldName =
13 | (Builtin.testDerrorMessage "Uncaught exception: error")
14 |
15 | (let x = 6L in x.fieldName) =
16 | (Builtin.testDerrorMessage
17 | "Attempting to perform field access of an Int64, but this only works with records")
--------------------------------------------------------------------------------
/backend/testfiles/httphandler/simple-response-headers.test:
--------------------------------------------------------------------------------
1 | [http-handler GET /]
2 | (let body = (Darklang.Stdlib.String.toBytes "1")
3 | let headers = [("header1", "value1"); ("Header2", "Value2"); ("Header-3", "Value-3")]
4 | Darklang.Stdlib.Http.responseWithHeaders body headers 200L)
5 |
6 | [request]
7 | GET / HTTP/1.1
8 | Host: HOST
9 | Date: Sun, 08 Nov 2020 15:38:01 GMT
10 | Content-Length: 7
11 |
12 | ignored
13 |
14 | [response]
15 | HTTP/1.1 200 OK
16 | Date: xxx, xx xxx xxxx xx:xx:xx xxx
17 | header-3: Value-3
18 | header2: Value2
19 | x-darklang-execution-id: 0123456789
20 | Server: darklang
21 | header1: value1
22 | Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
23 | Content-Length: 1
24 |
25 | 1
--------------------------------------------------------------------------------
/backend/testfiles/execution/language/basic/estring.dark:
--------------------------------------------------------------------------------
1 | $"""test {"1"}""" = "test 1"
2 |
3 | (let one = "1" in $"test {one}") = "test 1"
4 |
5 | (let one = 1.0 in $"test {one}") =
6 | Builtin.testDerrorMessage "Expected String in string interpolation, got a Float (1.0) instead"
7 |
8 | (let one = 1L in $"test {one}") =
9 | Builtin.testDerrorMessage "Expected String in string interpolation, got an Int64 (1) instead"
10 |
11 | (let name = "John"
12 | let age = "30"
13 | $"Name: {name}, Age: {age} years old.") = "Name: John, Age: 30 years old."
14 |
15 | (let two = 2L in "test 1" == $"test {one}") =
16 | Builtin.testDerrorMessage "There is no variable named: one"
17 |
18 | (let one = 1L in $"test {Stdlib.Int64.toString one}") = "test 1"
--------------------------------------------------------------------------------
/containers/bwdserver/Dockerfile:
--------------------------------------------------------------------------------
1 | # Dockerfile for the grand-user facing Dark app at darklang.io
2 |
3 | FROM darkfsharpservice:latest
4 |
5 | WORKDIR /home/dark
6 |
7 | COPY --chown=dark:dark scripts scripts
8 |
9 | # Add favicon
10 | RUN mkdir -p webroot/static
11 | COPY --chown=dark:dark backend/static/favicon-32x32.png webroot/static/favicon-32x32.png
12 |
13 | RUN mkdir app
14 |
15 | # Setting this now means we can set the filesystem to readonly
16 | ENV DARK_CONFIG_RUNDIR=/home/dark/gcp-rundir
17 | RUN ./scripts/devcontainer/_create-app-directories
18 |
19 | COPY --chown=dark:dark backend/Build/out/BwdServer/Release/net8.0/linux-x64/publish/* app/
20 | RUN ./scripts/linting/_check-linked-libs app/BwdServer
21 |
22 | CMD ./app/BwdServer
--------------------------------------------------------------------------------
/scripts/build/reload-packages:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./scripts/devcontainer/_assert-in-container "$0" "$@"
3 |
4 | set -euo pipefail
5 |
6 | TEST=false
7 | PUBLISHED_FLAG=
8 |
9 | for i in "$@"
10 | do
11 | case "${i}" in
12 | --test)
13 | TEST=true
14 | shift
15 | ;;
16 | --published)
17 | PUBLISHED_FLAG=$i
18 | ;;
19 | esac
20 | done
21 |
22 | if [[ "$TEST" == "true" ]]; then
23 | LOG_CANVAS="${DARK_CONFIG_RUNDIR}/logs/test-packages-canvas.log"
24 | else
25 | LOG_CANVAS="${DARK_CONFIG_RUNDIR}/logs/packages-canvas.log"
26 | fi
27 |
28 |
29 | ./scripts/run-local-exec $PUBLISHED_FLAG reload-packages > $LOG_CANVAS 2>&1
30 | echo -e "Done reloading packages from packages/**/*.dark files to internal SQLite DB"
--------------------------------------------------------------------------------
/backend/migrations/20250820_000000_rename_package_constants_to_values.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE IF NOT EXISTS
2 | package_values_v0
3 | ( id TEXT PRIMARY KEY
4 | , owner TEXT NOT NULL -- e.g. Darklang
5 | , modules TEXT NOT NULL -- e.g. Math.Geometry
6 | , name TEXT NOT NULL -- e.g. pi
7 | , pt_def BLOB -- serialized PT.PackageValue
8 | , rt_dval BLOB -- serialized RT.PackageValue
9 | , created_at TEXT NOT NULL DEFAULT (datetime('now'))
10 | );
11 |
12 | CREATE INDEX IF NOT EXISTS idx_package_values_pt_def
13 | ON package_values_v0(id) WHERE pt_def IS NOT NULL;
14 |
15 | CREATE INDEX IF NOT EXISTS idx_package_values_rt_dval
16 | ON package_values_v0(id) WHERE rt_dval IS NOT NULL;
17 |
18 | -- Drop the package_constants_v0 table
19 | DROP TABLE package_constants_v0;
--------------------------------------------------------------------------------
/packages/darklang/languageTools/common.dark:
--------------------------------------------------------------------------------
1 | module Darklang.LanguageTools
2 |
3 |
4 | // TODO: should this be UInt64?
5 | type ID = Int64
6 |
7 | type TLID = UInt64
8 |
9 | type Sign =
10 | | Positive
11 | | Negative
12 |
13 | type BuiltinFunctionParameter =
14 | { name: String
15 | ``type``: RuntimeTypes.TypeReference }
16 |
17 | /// A Darklang builtin function
18 | type BuiltinFunction =
19 | { name: RuntimeTypes.FQFnName.Builtin
20 | description: String
21 | parameters: List
22 | returnType: RuntimeTypes.TypeReference }
23 |
24 | /// A Darklang builtin value
25 | type BuiltinValue =
26 | { name: RuntimeTypes.FQValueName.Builtin
27 | description: String
28 | ``type``: RuntimeTypes.TypeReference }
29 |
--------------------------------------------------------------------------------
/docs/benchmarking.md:
--------------------------------------------------------------------------------
1 | # Some notes on benchmarking
2 |
3 | ## General
4 |
5 | - Benchmarking in a VS Code container doesn't work - VS Code seems to do something to each request
6 | - the F# server will happily spread out to lots of cores and it's hard to siturate it. At `--cpus 2` it's easier to watch
7 | - ensure you optimize by passing the `--optimize` flag to `scripts/builder` or `scripts/build/_build-server`
8 |
9 | ## Profiling .NET
10 |
11 | - dotnet tool install dotnet-trace
12 | - dotnet trace ps # get id of BwdServer
13 | - dotnet trace collect --format SpeedScope -p ID
14 | - upload the file to https://speedscope.app for a flame graph
15 |
16 | ## Using ab
17 |
18 | - sudo apt install apache2-utils # install
19 | - ab -n 2000 -c 50 URL # good settings
20 |
--------------------------------------------------------------------------------
/backend/src/LibClientTypes/LibClientTypes.fsproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Library
5 | net8.0
6 | 8.0
7 |
8 | false
9 | false
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/backend/src/LibPackageManager/Caching.fs:
--------------------------------------------------------------------------------
1 | module LibPackageManager.Caching
2 |
3 | open System.Threading.Tasks
4 | open FSharp.Control.Tasks
5 | open System.Collections.Concurrent
6 |
7 | open Prelude
8 |
9 |
10 | let withCache (f : 'key -> Ply