diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..fe07df655 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +d2layouts/d2dagrelayout/dagre.js linguist-vendored +d2layouts/d2elklayout/elk.js linguist-vendored +d2renderers/d2svg/github-markdown.css linguist-vendored diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e61c2ae64..f24865554 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,2 +1,3 @@ + diff --git a/README.md b/README.md index 22a738321..df9cd9564 100644 --- a/README.md +++ b/README.md @@ -20,27 +20,28 @@ -- [Quickstart (CLI)](#quickstart-cli) - * [MacOS](#macos) - * [Linux/Windows](#linuxwindows) -- [Quickstart (library)](#quickstart-library) +- [Quickstart](#quickstart) +- [Install](#install) + * [Install script](#install-script) + * [Install from source](#install-from-source) +- [D2 as a library](#d2-as-a-library) - [Themes](#themes) - [Fonts](#fonts) - [Export file types](#export-file-types) - [Language tooling](#language-tooling) -- [Layout engine](#layout-engine) +- [Plugins](#plugins) - [Comparison](#comparison) - [Contributing](#contributing) - [License](#license) -- [Dependencies](#dependencies) - [Related](#related) * [VSCode extension](#vscode-extension) * [Vim extension](#vim-extension) * [Misc](#misc) +- [FAQ](#faq) -## Quickstart (CLI) +## Quickstart The most convenient way to use D2 is to just run it as a CLI executable to produce SVGs from `.d2` files. @@ -55,22 +56,17 @@ d2 --watch in.d2 out.svg A browser window will open with `out.svg` and live-reload on changes to `in.d2`. -### Install from source +## Install -```sh -go install oss.terrastruct.com/d2 -``` - -### Install +### Install script The recommended way to install is to run our install script, which will figure out the -best way to install based on your machine. E.g. if D2 is available through a package -manager installed, it will use that package manager. +best way to install based on your machine. ```sh -# With --dryrun the install script will print the commands it will use +# With --dry-run the install script will print the commands it will use # to install without actually installing so you know what it's going to do. -curl -fsSL https://d2lang.com/install.sh | sh -s -- --dryrun +curl -fsSL https://d2lang.com/install.sh | sh -s -- --dry-run # If things look good, install for real. curl -fsSL https://d2lang.com/install.sh | sh -s -- ``` @@ -83,7 +79,7 @@ and release a docker image. To uninstall: ```sh -curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall --dryrun +curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall --dry-run # If things look good, uninstall for real. curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall ``` @@ -91,18 +87,26 @@ curl -fsSL https://d2lang.com/install.sh | sh -s -- --uninstall > warn: Our binary releases aren't fully portable like normal Go binaries due to the C > dependency on v8go for executing dagre. -## Quickstart (library) +### Install from source + +Alternatively, you can install from source: + +```sh +go install oss.terrastruct.com/d2 +``` + +## D2 as a library In addition to being a runnable CLI tool, D2 can also be used to produce diagrams from Go programs. ```go import ( - "github.com/terrastruct/d2/d2compiler" - "github.com/terrastruct/d2/d2exporter" - "github.com/terrastruct/d2/d2layouts/d2dagrelayout" - "github.com/terrastruct/d2/d2renderers/textmeasure" - "github.com/terrastruct/d2/d2themes/d2themescatalog" + "github.com/terrastruct/d2/d2compiler" + "github.com/terrastruct/d2/d2exporter" + "github.com/terrastruct/d2/d2layouts/d2dagrelayout" + "github.com/terrastruct/d2/d2renderers/textmeasure" + "github.com/terrastruct/d2/d2themes/d2themescatalog" ) func main() { @@ -208,10 +212,13 @@ Copyright © 2022 Terrastruct, Inc. Open-source licensed under the Mozilla Publi [https://github.com/terrastruct/d2-vim](https://github.com/terrastruct/d2-vim) +### Language docs + +[https://github.com/terrastruct/d2-docs](https://github.com/terrastruct/d2-docs) + ### Misc -- [https://github.com/terrastruct/d2-docs](https://github.com/terrastruct/d2-docs) -- [https://github.com/terrastruct/text-to-diagram-com](https://github.com/terrastruct/text-to-diagram-com) +- [https://github.com/terrastruct/text-to-diagram-site](https://github.com/terrastruct/text-to-diagram-site) ## FAQ @@ -221,10 +228,8 @@ Copyright © 2022 Terrastruct, Inc. Open-source licensed under the Mozilla Publi - Does D2 need a browser to run? - No, D2 can run entirely server-side. - I have a question or need help. - - The best way to get help is to open an Issue, so that it's searchable by others in the - future. If you prefer synchronous or just want to chat, you can pop into the help - channel of the [D2 Discord](https://discord.gg/NF6X8K4eDq) as well. -- I have a feature request or proposal. - - D2 uses Github Issues for everything. Just add a "discussion" label to your Issue. + - The best way to get help is to ask on [D2 Discord](https://discord.gg/NF6X8K4eDq) +- I have a feature request, proposal, or bug report. + - Please open up a Github Issue. - I have a private inquiry. - Please reach out at [hi@d2lang.com](hi@d2lang.com). diff --git a/ci/release/_install.sh b/ci/release/_install.sh index 7afd53f1e..7406eca3f 100755 --- a/ci/release/_install.sh +++ b/ci/release/_install.sh @@ -194,7 +194,7 @@ EOF if ! manpath | grep -qF "$PREFIX/share/man"; then logcat >&2 </d2---.tar.gz @@ -35,6 +35,9 @@ Flags: --version vX.X.X Use to overwrite the version detected from git. + +--lockfile-force + Forcefully take ownership of remote builder lockfiles. EOF } @@ -71,6 +74,10 @@ main() { flag_nonemptyarg && shift "$FLAGSHIFT" VERSION=$FLAGARG ;; + lockfile-force) + flag_noarg && shift "$FLAGSHIFT" + LOCKFILE_FORCE=1 + ;; '') shift "$FLAGSHIFT" break @@ -118,10 +125,10 @@ build() { macos) case $ARCH in amd64) - RHOST=$TSTRUCT_MACOS_AMD64_BUILDER build_rhost_macos + REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER build_remote_macos ;; arm64) - RHOST=$TSTRUCT_MACOS_ARM64_BUILDER build_rhost_macos + REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER build_remote_macos ;; *) warn "no builder for OS=$OS ARCH=$ARCH, building locally..." @@ -132,10 +139,10 @@ build() { linux) case $ARCH in amd64) - RHOST=$TSTRUCT_LINUX_AMD64_BUILDER build_rhost_linux + REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER build_remote_linux ;; arm64) - RHOST=$TSTRUCT_LINUX_ARM64_BUILDER build_rhost_linux + REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER build_remote_linux ;; *) warn "no builder for OS=$OS ARCH=$ARCH, building locally..." @@ -160,10 +167,12 @@ build_local() { sh_c ./ci/release/_build.sh } -build_rhost_macos() { - sh_c ssh "$RHOST" mkdir -p src - sh_c rsync --archive --human-readable --delete ./ "$RHOST:src/d2/" - sh_c ssh -tttt "$RHOST" "DRY_RUN=${DRY_RUN-} \ +build_remote_macos() { + sh_c lockfile_ssh "$REMOTE_HOST" .d2-build-lock + trap unlockfile_ssh EXIT + sh_c ssh "$REMOTE_HOST" mkdir -p src + sh_c rsync --archive --human-readable --delete ./ "$REMOTE_HOST:src/d2/" + sh_c ssh "$REMOTE_HOST" "DRY_RUN=${DRY_RUN-} \ HW_BUILD_DIR=$HW_BUILD_DIR \ VERSION=$VERSION \ OS=$OS \ @@ -173,13 +182,15 @@ TERM=$TERM \ PATH=\\\"/usr/local/bin:/usr/local/sbin:/opt/homebrew/bin:/opt/homebrew/sbin\\\${PATH+:\\\$PATH}\\\" \ ./src/d2/ci/release/_build.sh" sh_c mkdir -p "$HW_BUILD_DIR" - sh_c rsync --archive --human-readable "$RHOST:src/d2/$ARCHIVE" "$ARCHIVE" + sh_c rsync --archive --human-readable "$REMOTE_HOST:src/d2/$ARCHIVE" "$ARCHIVE" } -build_rhost_linux() { - sh_c ssh "$RHOST" mkdir -p src - sh_c rsync --archive --human-readable --delete ./ "$RHOST:src/d2/" - sh_c ssh -tttt "$RHOST" "DRY_RUN=${DRY_RUN-} \ +build_remote_linux() { + sh_c lockfile_ssh "$REMOTE_HOST" .d2-build-lock + trap unlockfile_ssh EXIT + sh_c ssh "$REMOTE_HOST" mkdir -p src + sh_c rsync --archive --human-readable --delete ./ "$REMOTE_HOST:src/d2/" + sh_c ssh "$REMOTE_HOST" "DRY_RUN=${DRY_RUN-} \ HW_BUILD_DIR=$HW_BUILD_DIR \ VERSION=$VERSION \ OS=$OS \ @@ -188,7 +199,7 @@ ARCHIVE=$ARCHIVE \ TERM=$TERM \ ./src/d2/ci/release/build_docker.sh" sh_c mkdir -p "$HW_BUILD_DIR" - sh_c rsync --archive --human-readable "$RHOST:src/d2/$ARCHIVE" "$ARCHIVE" + sh_c rsync --archive --human-readable "$REMOTE_HOST:src/d2/$ARCHIVE" "$ARCHIVE" } ssh() { diff --git a/ci/release/builders/aws_copy_keys.sh b/ci/release/builders/aws_copy_keys.sh new file mode 100755 index 000000000..df5c46408 --- /dev/null +++ b/ci/release/builders/aws_copy_keys.sh @@ -0,0 +1,61 @@ +#!/bin/sh +set -eu +cd -- "$(dirname "$0")/../../.." +. ./ci/sub/lib.sh + +help() { + cat < .ssh/authorized_keys.dedup' + sh_c ssh "$REMOTE_HOST" 'cp .ssh/authorized_keys.dedup .ssh/authorized_keys' + sh_c ssh "$REMOTE_HOST" 'rm .ssh/authorized_keys.dedup' +} + +main "$@" diff --git a/ci/release/builders/aws_ensure.sh b/ci/release/builders/aws_ensure.sh index dfeb3443c..3a875d832 100755 --- a/ci/release/builders/aws_ensure.sh +++ b/ci/release/builders/aws_ensure.sh @@ -41,12 +41,12 @@ main() { fi if [ -z "${SKIP_CREATE-}" ]; then - create_rhosts + create_remote_hosts fi - init_rhosts + init_remote_hosts } -create_rhosts() { +create_remote_hosts() { KEY_NAME=$(aws ec2 describe-key-pairs | jq -r .KeyPairs[0].KeyName) VPC_ID=$(aws ec2 describe-vpcs | jq -r .Vpcs[0].VpcId) @@ -77,7 +77,7 @@ create_rhosts() { | jq -r '.Reservations[].Instances[].State.Name') if [ -z "$state" ]; then sh_c aws ec2 run-instances \ - --image-id=ami-0d593311db5abb72b \ + --image-id=ami-071e6cafc48327ca2 \ --count=1 \ --instance-type=t2.small \ --security-groups=ssh \ @@ -90,8 +90,8 @@ create_rhosts() { --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-amd64' \ | jq -r '.Reservations[].Instances[].PublicDnsName') if [ -n "$dnsname" ]; then - log "TSTRUCT_LINUX_AMD64_BUILDER=ec2-user@$dnsname" - export TSTRUCT_LINUX_AMD64_BUILDER=ec2-user@$dnsname + log "TSTRUCT_LINUX_AMD64_BUILDER=admin@$dnsname" + export TSTRUCT_LINUX_AMD64_BUILDER=admin@$dnsname break fi sleep 5 @@ -103,7 +103,7 @@ create_rhosts() { | jq -r '.Reservations[].Instances[].State.Name') if [ -z "$state" ]; then sh_c aws ec2 run-instances \ - --image-id=ami-0efabcf945ffd8831 \ + --image-id=ami-0e67506f183e5ab60 \ --count=1 \ --instance-type=t4g.small \ --security-groups=ssh \ @@ -116,8 +116,8 @@ create_rhosts() { --filters 'Name=instance-state-name,Values=pending,running,stopping,stopped' 'Name=tag:Name,Values=d2-builder-linux-arm64' \ | jq -r '.Reservations[].Instances[].PublicDnsName') if [ -n "$dnsname" ]; then - log "TSTRUCT_LINUX_ARM64_BUILDER=ec2-user@$dnsname" - export TSTRUCT_LINUX_ARM64_BUILDER=ec2-user@$dnsname + log "TSTRUCT_LINUX_ARM64_BUILDER=admin@$dnsname" + export TSTRUCT_LINUX_ARM64_BUILDER=admin@$dnsname break fi sleep 5 @@ -194,15 +194,15 @@ create_rhosts() { done } -init_rhosts() { +init_remote_hosts() { header linux-amd64 - RHOST=$TSTRUCT_LINUX_AMD64_BUILDER init_rhost_linux + REMOTE_HOST=$TSTRUCT_LINUX_AMD64_BUILDER init_remote_linux header linux-arm64 - RHOST=$TSTRUCT_LINUX_ARM64_BUILDER init_rhost_linux + REMOTE_HOST=$TSTRUCT_LINUX_ARM64_BUILDER init_remote_linux header macos-amd64 - RHOST=$TSTRUCT_MACOS_AMD64_BUILDER init_rhost_macos + REMOTE_HOST=$TSTRUCT_MACOS_AMD64_BUILDER init_remote_macos header macos-arm64 - RHOST=$TSTRUCT_MACOS_ARM64_BUILDER init_rhost_macos + REMOTE_HOST=$TSTRUCT_MACOS_ARM64_BUILDER init_remote_macos COLOR=2 header summary log "export TSTRUCT_LINUX_AMD64_BUILDER=$TSTRUCT_LINUX_AMD64_BUILDER" @@ -211,32 +211,53 @@ init_rhosts() { log "export TSTRUCT_MACOS_ARM64_BUILDER=$TSTRUCT_MACOS_ARM64_BUILDER" } -init_rhost_linux() { +init_remote_linux() { while true; do - if sh_c ssh "$RHOST" :; then + if sh_c ssh "$REMOTE_HOST" :; then break fi sleep 5 done - sh_c ssh "$RHOST" 'sudo yum upgrade -y' - sh_c ssh "$RHOST" 'sudo yum install -y docker' - sh_c ssh "$RHOST" 'sudo systemctl start docker' - sh_c ssh "$RHOST" 'sudo systemctl enable docker' - sh_c ssh "$RHOST" 'sudo usermod -a -G docker ec2-user' - sh_c ssh "$RHOST" 'sudo reboot' || true + + sh_c ssh "$REMOTE_HOST" sh -s -- < /dev/null +sudo -E apt-get update -y +sudo -E apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin +sudo groupadd docker || true +sudo usermod -aG docker \$USER +EOF + + sh_c ssh "$REMOTE_HOST" 'sudo reboot' || true } -init_rhost_macos() { +init_remote_macos() { while true; do - if sh_c ssh "$RHOST" :; then + if sh_c ssh "$REMOTE_HOST" :; then break fi sleep 5 done - sh_c ssh "$RHOST" '": | /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""' - sh_c ssh "$RHOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew update' - sh_c ssh "$RHOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew upgrade' - sh_c ssh "$RHOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew install go' + sh_c ssh "$REMOTE_HOST" '"/bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""' + sh_c ssh "$REMOTE_HOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew update' + sh_c ssh "$REMOTE_HOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew upgrade' + sh_c ssh "$REMOTE_HOST" 'PATH="/usr/local/bin:/opt/homebrew/bin:\$PATH" brew install go' } main "$@" diff --git a/ci/release/builders/aws_ssh_copy_id.sh b/ci/release/builders/aws_ssh_copy_id.sh deleted file mode 100755 index d50a96d9d..000000000 --- a/ci/release/builders/aws_ssh_copy_id.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh -set -eu -cd -- "$(dirname "$0")/../../.." -. ./ci/sub/lib.sh - -help() { - cat <= 3 { return xmain.UsageErrorf("too many arguments passed") } + if len(ms.Opts.Args()) >= 1 { if ms.Opts.Arg(0) == "version" { - version.CheckVersion(ctx, ms.Log) + fmt.Println(version.Version) return nil } inputPath = ms.Opts.Arg(0) diff --git a/d2ast/d2ast.go b/d2ast/d2ast.go index 69fa544fe..fa2cefffa 100644 --- a/d2ast/d2ast.go +++ b/d2ast/d2ast.go @@ -1,8 +1,5 @@ // d2ast implements the d2 language's abstract syntax tree. // -// https://github.com/terrastruct/d2-vscode -// https://terrastruct.com/docs/d2/tour/intro/ -// // Special characters to think about in parser: // # // """ diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 895b86d75..0db0d62d4 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -680,12 +680,12 @@ func (c *compiler) compileSQLTable(obj *d2graph.Object) { continue } if srcID == absID { - // Frontend isn't aware of container IDs. d2Col.Reference = strings.TrimPrefix(dstID, parentID+".") - relSrc := strings.TrimPrefix(absID, parentID+".") - e.Attributes.Label.Value = fmt.Sprintf("%s %s %s", relSrc, e.ArrowString(), d2Col.Reference) - // removeContainer() will adjust the edge to point to the table and not inside. - break + e.SrcTableColumnIndex = new(int) + *e.SrcTableColumnIndex = len(obj.SQLTable.Columns) + } else if dstID == absID { + e.DstTableColumnIndex = new(int) + *e.DstTableColumnIndex = len(obj.SQLTable.Columns) } } @@ -746,6 +746,14 @@ func flattenContainer(g *d2graph.Graph, obj *d2graph.Object) { newEdge, _ = g.Root.Connect(e.Src.AbsIDArray(), obj.AbsIDArray(), e.SrcArrow, e.DstArrow, e.Attributes.Label.Value) } // TODO more attributes + if e.SrcTableColumnIndex != nil { + newEdge.SrcTableColumnIndex = new(int) + *newEdge.SrcTableColumnIndex = *e.SrcTableColumnIndex + } + if e.DstTableColumnIndex != nil { + newEdge.DstTableColumnIndex = new(int) + *newEdge.DstTableColumnIndex = *e.DstTableColumnIndex + } newEdge.Attributes.Label = e.Attributes.Label newEdge.References = e.References } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 54f59d64c..c43639cb8 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -1474,6 +1474,32 @@ b`, g.Objects[0].Attributes.Label.Value) SVP1.style.3d: true`, expErr: `d2/testdata/d2compiler/TestCompile/3d_oval.d2:2:1: key "3d" can only be applied to squares and rectangles `, + }, { + name: "edge_column_index", + text: `src: { + shape: sql_table + id: int + dst_id: int +} + +dst: { + shape: sql_table + id: int + name: string +} + +dst.id <-> src.dst_id +`, + assertions: func(t *testing.T, g *d2graph.Graph) { + srcIndex := g.Edges[0].SrcTableColumnIndex + if srcIndex == nil || *srcIndex != 0 { + t.Fatalf("expected SrcTableColumnIndex to be 0, got %v", srcIndex) + } + dstIndex := g.Edges[0].DstTableColumnIndex + if dstIndex == nil || *dstIndex != 1 { + t.Fatalf("expected DstTableColumnIndex to be 1, got %v", dstIndex) + } + }, }, } diff --git a/d2compiler/doc.go b/d2compiler/doc.go index 03799880e..401d9eb3f 100644 --- a/d2compiler/doc.go +++ b/d2compiler/doc.go @@ -1,6 +1,3 @@ // Package d2compiler implements a parser, compiler and autoformatter for the Terrastruct d2 // diagramming language. -// -// https://github.com/terrastruct/d2-vscode -// https://terrastruct.com/docs/d2/tour/intro/ package d2compiler diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index aef91878f..5687608f1 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -607,6 +607,9 @@ type Edge struct { MinWidth int `json:"minWidth"` MinHeight int `json:"minHeight"` + SrcTableColumnIndex *int `json:"srcTableColumnIndex,omitempty"` + DstTableColumnIndex *int `json:"dstTableColumnIndex,omitempty"` + LabelDimensions d2target.TextDimensions `json:"label_dimensions"` LabelPosition *string `json:"labelPosition,omitempty"` LabelPercentage *float64 `json:"labelPercentage,omitempty"` diff --git a/d2layouts/d2dagrelayout/NOTICE.txt b/d2layouts/d2dagrelayout/NOTICE.txt new file mode 100644 index 000000000..cac5f33be --- /dev/null +++ b/d2layouts/d2dagrelayout/NOTICE.txt @@ -0,0 +1,6 @@ +dagre.js comes from https://github.com/dagrejs/dagre + +Attribution: + +MIT License +https://github.com/dagrejs/dagre/blob/master/LICENSE diff --git a/d2layouts/d2elklayout/NOTICE.txt b/d2layouts/d2elklayout/NOTICE.txt new file mode 100644 index 000000000..6fdaba655 --- /dev/null +++ b/d2layouts/d2elklayout/NOTICE.txt @@ -0,0 +1,6 @@ +elk.js comes from https://github.com/kieler/elkjs + +Attribution: + +EPL License 2.0 +https://github.com/kieler/elkjs/blob/master/LICENSE.md diff --git a/d2layouts/d2elklayout/layout.go b/d2layouts/d2elklayout/layout.go index 762b85f17..eaadd520c 100644 --- a/d2layouts/d2elklayout/layout.go +++ b/d2layouts/d2elklayout/layout.go @@ -12,7 +12,6 @@ import ( "math" "rogchap.com/v8go" - v8 "rogchap.com/v8go" "oss.terrastruct.com/xdefer" @@ -104,7 +103,7 @@ func Layout(ctx context.Context, g *d2graph.Graph) (err error) { }) global.Set("setTimeout", setTimeout, v8go.ReadOnly) - v8ctx := v8.NewContext(iso, global) + v8ctx := v8go.NewContext(iso, global) if _, err := v8ctx.RunScript(elkJS, "elk.js"); err != nil { return err } diff --git a/d2themes/d2themes.go b/d2themes/d2themes.go index 5ea17bd6f..c5217c592 100644 --- a/d2themes/d2themes.go +++ b/d2themes/d2themes.go @@ -18,9 +18,6 @@ type Neutral struct { } type ColorPalette struct { - // So far the palette only contains the colors used in d2 shapes, the full theme includes more colors - // https://www.figma.com/file/n79RbPiHFUTO4PPPdpDu7w/%5BKW%5D-GUI-features?node-id=2268%3A120792 - Neutrals Neutral `json:"neutrals"` // Base Colors: used for containers diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index c9a1a87fc..ab7d770a9 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -831,6 +831,43 @@ a -> md -> b +setTimeout(seconds int) } `, + }, { + name: "sql_tables", + script: `users: { + shape: sql_table + id: int + name: string + email: string + password: string + last_login: datetime +} + +products: { + shape: sql_table + id: int + price: decimal + sku: string + name: string +} + +orders: { + shape: sql_table + id: int + user_id: int + product_id: int +} + +shipments: { + shape: sql_table + id: int + order_id: int + tracking_number: string + status: string +} + +users.id <-> orders.user_id +products.id <-> orders.product_id +shipments.order_id <-> orders.id`, }, } diff --git a/e2etests/testdata/stable/sql_tables/dagre/board.exp.json b/e2etests/testdata/stable/sql_tables/dagre/board.exp.json new file mode 100644 index 000000000..da031d9b2 --- /dev/null +++ b/e2etests/testdata/stable/sql_tables/dagre/board.exp.json @@ -0,0 +1,396 @@ +{ + "name": "", + "shapes": [ + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 0, + "y": 0 + }, + "width": 259, + "height": 216, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "orders.user_id" + }, + { + "name": "name", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "email", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "password", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "last_login", + "type": "datetime", + "constraint": "", + "reference": "" + } + ], + "label": "users", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 61, + "labelHeight": 36 + }, + { + "id": "products", + "type": "sql_table", + "pos": { + "x": 319, + "y": 18 + }, + "width": 290, + "height": 180, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "orders.product_id" + }, + { + "name": "price", + "type": "decimal", + "constraint": "", + "reference": "" + }, + { + "name": "sku", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "name", + "type": "string", + "constraint": "", + "reference": "" + } + ], + "label": "products", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 99, + "labelHeight": 36 + }, + { + "id": "orders", + "type": "sql_table", + "pos": { + "x": 357, + "y": 316 + }, + "width": 215, + "height": 144, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "" + }, + { + "name": "user_id", + "type": "int", + "constraint": "", + "reference": "" + }, + { + "name": "product_id", + "type": "int", + "constraint": "", + "reference": "" + } + ], + "label": "orders", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 74, + "labelHeight": 36 + }, + { + "id": "shipments", + "type": "sql_table", + "pos": { + "x": 669, + "y": 18 + }, + "width": 293, + "height": 180, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "" + }, + { + "name": "order_id", + "type": "int", + "constraint": "", + "reference": "orders.id" + }, + { + "name": "tracking_number", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "status", + "type": "string", + "constraint": "", + "reference": "" + } + ], + "label": "shipments", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 116, + "labelHeight": 36 + } + ], + "connections": [ + { + "id": "(users <-> orders)[0]", + "src": "users", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "orders", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 129.5, + "y": 216 + }, + { + "x": 129.5, + "y": 256 + }, + { + "x": 174.9, + "y": 282.55844544095663 + }, + { + "x": 356.5, + "y": 348.7922272047833 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null + }, + { + "id": "(products <-> orders)[0]", + "src": "products", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "orders", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 464, + "y": 198 + }, + { + "x": 464, + "y": 252.4 + }, + { + "x": 464, + "y": 276 + }, + { + "x": 464, + "y": 316 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null + }, + { + "id": "(shipments <-> orders)[0]", + "src": "shipments", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "orders", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 815.5, + "y": 198 + }, + { + "x": 815.5, + "y": 252.4 + }, + { + "x": 766.7, + "y": 283 + }, + { + "x": 571.5, + "y": 351 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null + } + ] +} diff --git a/e2etests/testdata/stable/sql_tables/dagre/sketch.exp.svg b/e2etests/testdata/stable/sql_tables/dagre/sketch.exp.svg new file mode 100644 index 000000000..065687658 --- /dev/null +++ b/e2etests/testdata/stable/sql_tables/dagre/sketch.exp.svg @@ -0,0 +1,56 @@ + +usersid +int +name +string +email +string +password +string +last_login +datetime +productsid +int +price +decimal +sku +string +name +string +ordersid +int +user_id +int +product_id +int +shipmentsid +int +order_id +int +tracking_number +string +status +string + \ No newline at end of file diff --git a/e2etests/testdata/stable/sql_tables/elk/board.exp.json b/e2etests/testdata/stable/sql_tables/elk/board.exp.json new file mode 100644 index 000000000..abc5d00bf --- /dev/null +++ b/e2etests/testdata/stable/sql_tables/elk/board.exp.json @@ -0,0 +1,385 @@ +{ + "name": "", + "shapes": [ + { + "id": "users", + "type": "sql_table", + "pos": { + "x": 46, + "y": 412 + }, + "width": 259, + "height": 216, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "orders.user_id" + }, + { + "name": "name", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "email", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "password", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "last_login", + "type": "datetime", + "constraint": "", + "reference": "" + } + ], + "label": "users", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 61, + "labelHeight": 36 + }, + { + "id": "products", + "type": "sql_table", + "pos": { + "x": 15, + "y": 212 + }, + "width": 290, + "height": 180, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "orders.product_id" + }, + { + "name": "price", + "type": "decimal", + "constraint": "", + "reference": "" + }, + { + "name": "sku", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "name", + "type": "string", + "constraint": "", + "reference": "" + } + ], + "label": "products", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 99, + "labelHeight": 36 + }, + { + "id": "orders", + "type": "sql_table", + "pos": { + "x": 405, + "y": 230 + }, + "width": 215, + "height": 144, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "" + }, + { + "name": "user_id", + "type": "int", + "constraint": "", + "reference": "" + }, + { + "name": "product_id", + "type": "int", + "constraint": "", + "reference": "" + } + ], + "label": "orders", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 74, + "labelHeight": 36 + }, + { + "id": "shipments", + "type": "sql_table", + "pos": { + "x": 12, + "y": 12 + }, + "width": 293, + "height": 180, + "level": 1, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "#FFFFFF", + "stroke": "#0A0F25", + "shadow": false, + "3d": false, + "multiple": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "fields": null, + "methods": null, + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "" + }, + { + "name": "order_id", + "type": "int", + "constraint": "", + "reference": "orders.id" + }, + { + "name": "tracking_number", + "type": "string", + "constraint": "", + "reference": "" + }, + { + "name": "status", + "type": "string", + "constraint": "", + "reference": "" + } + ], + "label": "shipments", + "fontSize": 20, + "fontFamily": "DEFAULT", + "language": "", + "color": "#0A0F25", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 116, + "labelHeight": 36 + } + ], + "connections": [ + { + "id": "(users <-> orders)[0]", + "src": "users", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "orders", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 305, + "y": 520 + }, + { + "x": 355, + "y": 520 + }, + { + "x": 355, + "y": 338 + }, + { + "x": 405, + "y": 338 + } + ], + "animated": false, + "tooltip": "", + "icon": null + }, + { + "id": "(products <-> orders)[0]", + "src": "products", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "orders", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 305, + "y": 302 + }, + { + "x": 405, + "y": 302 + } + ], + "animated": false, + "tooltip": "", + "icon": null + }, + { + "id": "(shipments <-> orders)[0]", + "src": "shipments", + "srcArrow": "triangle", + "srcLabel": "", + "dst": "orders", + "dstArrow": "triangle", + "dstLabel": "", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "#0D32B2", + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "#676C7E", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "route": [ + { + "x": 305, + "y": 102 + }, + { + "x": 355, + "y": 102 + }, + { + "x": 355, + "y": 266 + }, + { + "x": 405, + "y": 266 + } + ], + "animated": false, + "tooltip": "", + "icon": null + } + ] +} diff --git a/e2etests/testdata/stable/sql_tables/elk/sketch.exp.svg b/e2etests/testdata/stable/sql_tables/elk/sketch.exp.svg new file mode 100644 index 000000000..e20e68fe8 --- /dev/null +++ b/e2etests/testdata/stable/sql_tables/elk/sketch.exp.svg @@ -0,0 +1,56 @@ + +usersid +int +name +string +email +string +password +string +last_login +datetime +productsid +int +price +decimal +sku +string +name +string +ordersid +int +user_id +int +product_id +int +shipmentsid +int +order_id +int +tracking_number +string +status +string + \ No newline at end of file diff --git a/go.mod b/go.mod index f0c96a553..72c8feb60 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/alecthomas/chroma v0.10.0 github.com/fsnotify/fsnotify v1.6.0 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 - github.com/google/go-github v17.0.0+incompatible github.com/lucasb-eyer/go-colorful v1.2.0 github.com/mazznoer/csscolorparser v0.1.3 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 @@ -21,8 +20,8 @@ require ( golang.org/x/text v0.3.7 gonum.org/v1/plot v0.12.0 nhooyr.io/websocket v1.8.7 - oss.terrastruct.com/cmdlog v0.0.0-20221025194258-d3fd7e0b8950 - oss.terrastruct.com/diff v1.0.1 + oss.terrastruct.com/cmdlog v0.0.0-20221116181457-07977d95ac37 + oss.terrastruct.com/diff v1.0.2-0.20221116222035-8bf4dd3ab541 oss.terrastruct.com/xcontext v0.0.0-20221018000442-50fdafb12f4f oss.terrastruct.com/xdefer v0.0.0-20221017222355-6f3b6e4d1557 oss.terrastruct.com/xjson v0.0.0-20221018000420-4986731c4c4a @@ -40,7 +39,6 @@ require ( github.com/gin-gonic/gin v1.7.7 // indirect github.com/go-playground/validator/v10 v10.10.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/go-querystring v1.1.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.13.6 // indirect diff --git a/go.sum b/go.sum index ac8c2599d..c9976a706 100644 --- a/go.sum +++ b/go.sum @@ -189,10 +189,6 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -772,10 +768,10 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= -oss.terrastruct.com/cmdlog v0.0.0-20221025194258-d3fd7e0b8950 h1:35gU5c1wwHKhXg58F500d6Ev8s+jqQUg4BiDbx2Zr+g= -oss.terrastruct.com/cmdlog v0.0.0-20221025194258-d3fd7e0b8950/go.mod h1:ROL3yxl2X+S3O+Rls00qdX6aMh+p1dF8IdxDRwDDpsg= -oss.terrastruct.com/diff v1.0.1 h1:WJ0LPXIgj644ne7l9CtDT9sBMDqo1B2/Ir5zdvbxYN8= -oss.terrastruct.com/diff v1.0.1/go.mod h1:cRGe5OvyjX7WWKk7CYh73SoS2tEghpTmAY1IPFWbqgE= +oss.terrastruct.com/cmdlog v0.0.0-20221116181457-07977d95ac37 h1:Xy1JKJHc4hcuwi57s0BvGUY16GjxTtBmLUybsuGDU7E= +oss.terrastruct.com/cmdlog v0.0.0-20221116181457-07977d95ac37/go.mod h1:ROL3yxl2X+S3O+Rls00qdX6aMh+p1dF8IdxDRwDDpsg= +oss.terrastruct.com/diff v1.0.2-0.20221116222035-8bf4dd3ab541 h1:I9B1O1IJ6spivIQxbFRZmbhAwVeLwrcQRR1JbYUOvrI= +oss.terrastruct.com/diff v1.0.2-0.20221116222035-8bf4dd3ab541/go.mod h1:ags2QDy/T6jr69hT6bpmAmhr2H98n9o8Atf3QlUJPiU= oss.terrastruct.com/xcontext v0.0.0-20221018000442-50fdafb12f4f h1:7voRCwKM7TZkTo9u7hj+uV/zXoVB8czWrTq6MVIh3dg= oss.terrastruct.com/xcontext v0.0.0-20221018000442-50fdafb12f4f/go.mod h1:Y0coTLsWwX0q3a+/Ndq797t+vWyxm42T49Ik3bzaDKY= oss.terrastruct.com/xdefer v0.0.0-20221017222355-6f3b6e4d1557 h1:rPbhJbN1q7B4tnppSPoAMwq0t6Pk5SrQDQ5S6uoNNHg= diff --git a/install.sh b/install.sh index fa42051a0..9c005b998 100755 --- a/install.sh +++ b/install.sh @@ -628,7 +628,7 @@ EOF if ! manpath | grep -qF "$PREFIX/share/man"; then logcat >&2 < %s", Version, latest) - } -} - -func getLatestVersion(ctx context.Context) (string, error) { - client := github.NewClient(nil) - rep, _, err := client.Repositories.GetLatestRelease(ctx, "terrastruct", "d2") - - if err != nil { - return "", err - } - - return *rep.TagName, nil -} diff --git a/testdata/d2compiler/TestCompile/edge_column_index.exp.json b/testdata/d2compiler/TestCompile/edge_column_index.exp.json new file mode 100644 index 000000000..8a9fde6d3 --- /dev/null +++ b/testdata/d2compiler/TestCompile/edge_column_index.exp.json @@ -0,0 +1,559 @@ +{ + "graph": { + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-13:0:123", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-4:1:48", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3", + "value": [ + { + "string": "src", + "raw_string": "src" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:5:5-4:0:47", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:1:8-1:17:24", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:1:8-1:6:13", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:1:8-1:6:13", + "value": [ + { + "string": "shape", + "raw_string": "shape" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,1:8:15-1:17:24", + "value": [ + { + "string": "sql_table", + "raw_string": "sql_table" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:1:26-2:8:33", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:1:26-2:3:28", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:1:26-2:3:28", + "value": [ + { + "string": "id", + "raw_string": "id" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,2:5:30-2:8:33", + "value": [ + { + "string": "int", + "raw_string": "int" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:1:35-3:12:46", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:1:35-3:7:41", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:1:35-3:7:41", + "value": [ + { + "string": "dst_id", + "raw_string": "dst_id" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,3:9:43-3:12:46", + "value": [ + { + "string": "int", + "raw_string": "int" + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-10:1:99", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53", + "value": [ + { + "string": "dst", + "raw_string": "dst" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:5:55-10:0:98", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:1:58-7:17:74", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:1:58-7:6:63", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:1:58-7:6:63", + "value": [ + { + "string": "shape", + "raw_string": "shape" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,7:8:65-7:17:74", + "value": [ + { + "string": "sql_table", + "raw_string": "sql_table" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:1:76-8:8:83", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:1:76-8:3:78", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:1:76-8:3:78", + "value": [ + { + "string": "id", + "raw_string": "id" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,8:5:80-8:8:83", + "value": [ + { + "string": "int", + "raw_string": "int" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:1:85-9:13:97", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:1:85-9:5:89", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:1:85-9:5:89", + "value": [ + { + "string": "name", + "raw_string": "name" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,9:7:91-9:13:97", + "value": [ + { + "string": "string", + "raw_string": "string" + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:21:122", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:21:122", + "src": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:7:108", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:3:104", + "value": [ + { + "string": "dst", + "raw_string": "dst" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:4:105-12:6:107", + "value": [ + { + "string": "id", + "raw_string": "id" + } + ] + } + } + ] + }, + "src_arrow": "<", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:10:111-12:21:122", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:11:112-12:14:115", + "value": [ + { + "string": "src", + "raw_string": "src" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:15:116-12:21:122", + "value": [ + { + "string": "dst_id", + "raw_string": "dst_id" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + } + } + }, + "edges": [ + { + "index": 0, + "minWidth": 0, + "minHeight": 0, + "srcTableColumnIndex": 0, + "dstTableColumnIndex": 1, + "label_dimensions": { + "width": 0, + "height": 0 + }, + "isCurve": false, + "src_arrow": true, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + } + } + } + ], + "objects": [ + { + "id": "src", + "id_val": "src", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,0:0:0-0:3:3", + "value": [ + { + "string": "src", + "raw_string": "src" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:10:111-12:21:122", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:11:112-12:14:115", + "value": [ + { + "string": "src", + "raw_string": "src" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:15:116-12:21:122", + "value": [ + { + "string": "dst_id", + "raw_string": "dst_id" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "sql_table": { + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "" + }, + { + "name": "dst_id", + "type": "int", + "constraint": "", + "reference": "" + } + ] + }, + "attributes": { + "label": { + "value": "src" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "sql_table" + } + } + }, + { + "id": "dst", + "id_val": "dst", + "label_dimensions": { + "width": 0, + "height": 0 + }, + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,6:0:50-6:3:53", + "value": [ + { + "string": "dst", + "raw_string": "dst" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:7:108", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:0:101-12:3:104", + "value": [ + { + "string": "dst", + "raw_string": "dst" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/edge_column_index.d2,12:4:105-12:6:107", + "value": [ + { + "string": "id", + "raw_string": "id" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "sql_table": { + "columns": [ + { + "name": "id", + "type": "int", + "constraint": "", + "reference": "src.dst_id" + }, + { + "name": "name", + "type": "string", + "constraint": "", + "reference": "" + } + ] + }, + "attributes": { + "label": { + "value": "dst" + }, + "style": {}, + "near_key": null, + "shape": { + "value": "sql_table" + } + } + } + ] + }, + "err": null +}