Initial commit with basic HTTP endpoint working
This commit is contained in:
commit
c77040304c
|
|
@ -0,0 +1,6 @@
|
|||
mermaidcli/node_modules/
|
||||
vendor/
|
||||
in/
|
||||
out/
|
||||
.DS_Store
|
||||
.idea/
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# Default ignored files
|
||||
/workspace.xml
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/mermaid-server.iml" filepath="$PROJECT_DIR$/.idea/mermaid-server.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions">
|
||||
<enabled-global>
|
||||
<option value="go fmt" />
|
||||
</enabled-global>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="ecb0f36f-87fb-46cd-8377-658fb925fcb6" name="Default Changelist" comment="">
|
||||
<change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/.gitignore" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/mermaid-server.iml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/watcherTasks.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/Dockerfile" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/cmd/app/main.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/internal/cache.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/internal/diagram.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/internal/generator.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/internal/http.go" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/mermaidcli/package-lock.json" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/mermaidcli/package.json" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Go File" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="GOROOT" path="/usr/local/Cellar/go/1.13.4/libexec" />
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="GoLibraries">
|
||||
<option name="indexEntireGoPath" value="false" />
|
||||
</component>
|
||||
<component name="IgnoredFileRootStore">
|
||||
<option name="generatedRoots">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$/.idea" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectId" id="1aAyop8moitN1kIl9HmAAe8m135" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showExcludedFiles" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="DefaultGoTemplateProperty" value="Go File" />
|
||||
<property name="NewWatcherDialog.advanced.open" value="true" />
|
||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="configurable.Global.GOPATH.is.expanded" value="true" />
|
||||
<property name="configurable.Project.GOPATH.is.expanded" value="true" />
|
||||
<property name="go.import.settings.migrated" value="true" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="node.js.detected.package.eslint" value="true" />
|
||||
<property name="node.js.detected.package.tslint" value="true" />
|
||||
<property name="node.js.path.for.package.eslint" value="project" />
|
||||
<property name="node.js.path.for.package.tslint" value="project" />
|
||||
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
||||
<property name="node.js.selected.package.tslint" value="(autodetect)" />
|
||||
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
||||
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
|
||||
<property name="settings.editor.selected.configurable" value="go.vgo" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="$PROJECT_DIR$" />
|
||||
<recent name="$PROJECT_DIR$/mermaidcli" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="app" type="GoApplicationRunConfiguration" factoryName="Go Application">
|
||||
<module name="mermaid-server" />
|
||||
<working_directory value="$PROJECT_DIR$/" />
|
||||
<go_parameters value="-i" />
|
||||
<parameters value="--mermaid=./mermaidcli/node_modules/.bin/mmdc --in=./in --out=./out" />
|
||||
<EXTENSION ID="net.ashald.envfile">
|
||||
<option name="IS_ENABLED" value="false" />
|
||||
<option name="IS_SUBST" value="false" />
|
||||
<option name="IS_PATH_MACRO_SUPPORTED" value="false" />
|
||||
<option name="IS_IGNORE_MISSING_FILES" value="false" />
|
||||
<option name="IS_ENABLE_EXPERIMENTAL_INTEGRATIONS" value="false" />
|
||||
<ENTRIES>
|
||||
<ENTRY IS_ENABLED="true" PARSER="runconfig" />
|
||||
</ENTRIES>
|
||||
</EXTENSION>
|
||||
<kind value="PACKAGE" />
|
||||
<filePath value="$PROJECT_DIR$/" />
|
||||
<package value="mermaid-server/cmd/app" />
|
||||
<directory value="$PROJECT_DIR$/" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="VgoProject">
|
||||
<integration-enabled>true</integration-enabled>
|
||||
<vendoring-mode>true</vendoring-mode>
|
||||
<proxy>direct</proxy>
|
||||
</component>
|
||||
<component name="WindowStateProjectService">
|
||||
<state x="184" y="112" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1586211567682">
|
||||
<screen x="0" y="0" width="1440" height="900" />
|
||||
</state>
|
||||
<state x="184" y="112" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.0.1440.900@0.0.1440.900" timestamp="1586211567682" />
|
||||
<state x="474" y="208" key="EnvironmentVariablesDialog" timestamp="1586194300455">
|
||||
<screen x="0" y="0" width="1440" height="900" />
|
||||
</state>
|
||||
<state x="474" y="208" key="EnvironmentVariablesDialog/0.0.1440.900@0.0.1440.900" timestamp="1586194300455" />
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.bottom" timestamp="1586211724295">
|
||||
<screen x="0" y="0" width="1440" height="900" />
|
||||
</state>
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.bottom/0.0.1440.900@0.0.1440.900" timestamp="1586211724295" />
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.center" timestamp="1586211724293">
|
||||
<screen x="0" y="0" width="1440" height="900" />
|
||||
</state>
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.center/0.0.1440.900@0.0.1440.900" timestamp="1586211724293" />
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.left" timestamp="1586211724292">
|
||||
<screen x="0" y="0" width="1440" height="900" />
|
||||
</state>
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.left/0.0.1440.900@0.0.1440.900" timestamp="1586211724292" />
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.right" timestamp="1586211724294">
|
||||
<screen x="0" y="0" width="1440" height="900" />
|
||||
</state>
|
||||
<state width="1398" height="226" key="GridCell.Tab.0.right/0.0.1440.900@0.0.1440.900" timestamp="1586211724294" />
|
||||
<state x="229" y="89" key="SettingsEditor" timestamp="1586192882553">
|
||||
<screen x="0" y="0" width="1440" height="900" />
|
||||
</state>
|
||||
<state x="229" y="89" key="SettingsEditor/0.0.1440.900@0.0.1440.900" timestamp="1586192882553" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# This stage builds the mermaidcli executable.
|
||||
FROM node:12.12.0-buster as node
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
# copy the mermaidcli node package into the container and install
|
||||
COPY ./mermaidcli/* .
|
||||
|
||||
RUN npm install
|
||||
|
||||
|
||||
# This stage builds the go executable.
|
||||
FROM golang:1.13-buster as go
|
||||
|
||||
WORKDIR /root
|
||||
COPY . .
|
||||
|
||||
RUN go build -o bin/app cmd/app/main.go
|
||||
|
||||
|
||||
# Final stage that will be pushed.
|
||||
FROM debian:buster-slim
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt update 2>/dev/null && \
|
||||
apt install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
2>/dev/null
|
||||
|
||||
COPY --from=node /root/node_modules/.bin/mmdc ./mermaidcli
|
||||
COPY --from=go /root/bin/app ./app
|
||||
|
||||
# We should now have all the required dependencies to build the proto files.
|
||||
CMD ["./app", "--mermaid=./mermaidcli"]
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# mermaid-server
|
||||
|
||||
Use mermaid-js to generate diagrams in a HTTP endpoint.
|
||||
|
||||
While this currently serves the diagrams via HTTP, it could easily be manipulated to server diagrams via other means.
|
||||
|
||||
## Basic usage
|
||||
|
||||
Start the HTTP server:
|
||||
```
|
||||
go run cmd/app/main.go --mermaid=./mermaidcli/node_modules/.bin/mmdc --in=./in --out=./out
|
||||
```
|
||||
|
||||
Send CURL request to generate a diagram:
|
||||
```
|
||||
curl --location --request POST 'http://localhost:80/generate' \
|
||||
--header 'Content-Type: text/plain' \
|
||||
--data-raw 'graph LR
|
||||
|
||||
A-->B
|
||||
B-->C
|
||||
C-->D
|
||||
C-->F
|
||||
'
|
||||
```
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"mermaid-server/internal"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
var testInput = []byte(`
|
||||
graph TB
|
||||
|
||||
subgraph "Jira"
|
||||
createTicket["Create ticket"]
|
||||
updateTicket["Update ticket"]
|
||||
fireWebhook["Fire webhook"]
|
||||
|
||||
createTicket-->fireWebhook
|
||||
updateTicket-->fireWebhook
|
||||
end
|
||||
|
||||
subgraph "Jira Webhook"
|
||||
receiveWebhook["Receive webhook"]
|
||||
storeEvent["Store event in immutable list"]
|
||||
publishNewStoredEventEvent["Publish message to notify system of new event"]
|
||||
|
||||
createEvent["Create internal event that will be stored"]
|
||||
setCreatedAt["Set created at date to now"]
|
||||
setSourceJira["Set source to Jira webhook"]
|
||||
|
||||
receiveWebhook-->createEvent-->setCreatedAt-->setSourceJira-->storeEvent
|
||||
storeEvent-->publishNewStoredEventEvent
|
||||
end
|
||||
|
||||
fireWebhook-->receiveWebhook
|
||||
|
||||
subgraph "Play Event"
|
||||
publishEventUpdated["Publish message to notify system of new status"]
|
||||
|
||||
verifyEventSource["Verify event source"]
|
||||
parsePayload["Parse event payload using source to determine structure"]
|
||||
findEventHandler["Find the handler for the specific event type + version"]
|
||||
getLatestPersistedState["Get latest persisted state"]
|
||||
changeInMemoryStateUsingEventData["Change in-memory state using event data"]
|
||||
persistUpdatedState["Persist updated state"]
|
||||
|
||||
verifyEventSource-->parsePayload
|
||||
parsePayload-->findEventHandler
|
||||
findEventHandler-->getLatestPersistedState-->changeInMemoryStateUsingEventData-->persistUpdatedState
|
||||
|
||||
persistUpdatedState-->publishEventUpdated
|
||||
end
|
||||
|
||||
publishNewStoredEventEvent-->verifyEventSource
|
||||
`)
|
||||
|
||||
func main() {
|
||||
mermaid := flag.String("mermaid", "", "The full path to the mermaidcli executable.")
|
||||
in := flag.String("in", "", "Directory to store input files.")
|
||||
out := flag.String("out", "", "Directory to store output files.")
|
||||
flag.Parse()
|
||||
|
||||
if *mermaid == "" {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Missing required argument `mermaid`")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *in == "" {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Missing required argument `in`")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *out == "" {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Missing required argument `out`")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cache := internal.NewDiagramCache()
|
||||
generator := internal.NewGenerator(cache, *mermaid, *in, *out)
|
||||
|
||||
httpHandler := internal.GenerateHTTPHandler(generator)
|
||||
|
||||
r := http.NewServeMux()
|
||||
r.Handle("/generate", http.HandlerFunc(httpHandler))
|
||||
|
||||
httpServer := &http.Server{
|
||||
Addr: ":80",
|
||||
Handler: r,
|
||||
}
|
||||
_, _ = fmt.Fprintf(os.Stdout, "Listening on address %s", httpServer.Addr)
|
||||
if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Could not listen for http connections: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stdout, "Shutdown")
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
package internal
|
||||
|
||||
// DiagramCache provides the ability to cache diagram results.
|
||||
type DiagramCache interface {
|
||||
// Store stores a diagram in the cache.
|
||||
Store(diagram *Diagram) error
|
||||
// Has returns true if we have a cache stored for the given diagram description.
|
||||
Has(diagram *Diagram) (bool, error)
|
||||
// Get returns a cached version of the given diagram description.
|
||||
Get(diagram *Diagram) (*Diagram, error)
|
||||
}
|
||||
|
||||
// NewDiagramCache returns an implementation of DiagramCache.
|
||||
func NewDiagramCache() DiagramCache {
|
||||
return &inMemoryDiagramCache{
|
||||
idToDiagram: map[string]*Diagram{},
|
||||
}
|
||||
}
|
||||
|
||||
// inMemoryDiagramCache is an in-memory implementation of DiagramCache.
|
||||
type inMemoryDiagramCache struct {
|
||||
idToDiagram map[string]*Diagram
|
||||
}
|
||||
|
||||
// Store stores a diagram in the cache.
|
||||
func (c *inMemoryDiagramCache) Store(diagram *Diagram) error {
|
||||
id, err := diagram.ID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.idToDiagram[id] = diagram
|
||||
return nil
|
||||
}
|
||||
|
||||
// Has returns true if we have a cache stored for the given diagram description.
|
||||
func (c *inMemoryDiagramCache) Has(diagram *Diagram) (bool, error) {
|
||||
id, err := diagram.ID()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if d, ok := c.idToDiagram[id]; ok && d != nil {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Get returns a cached version of the given diagram description.
|
||||
func (c *inMemoryDiagramCache) Get(diagram *Diagram) (*Diagram, error) {
|
||||
id, err := diagram.ID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d, ok := c.idToDiagram[id]; ok && d != nil {
|
||||
return d, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NewDiagram returns a new diagram.
|
||||
func NewDiagram(description []byte) *Diagram {
|
||||
return &Diagram{
|
||||
description: []byte(strings.TrimSpace(string(description))),
|
||||
}
|
||||
}
|
||||
|
||||
type Diagram struct {
|
||||
// iD is the ID of the Diagram
|
||||
id string
|
||||
// description is the description of the diagram.
|
||||
description []byte
|
||||
// Output is the filepath to the output file.
|
||||
Output string
|
||||
}
|
||||
|
||||
// ID returns an ID for the diagram.
|
||||
// The ID is set from the diagram description.
|
||||
func (d *Diagram) ID() (string, error) {
|
||||
if d.id != "" {
|
||||
return d.id, nil
|
||||
}
|
||||
|
||||
encoded := base64.StdEncoding.EncodeToString(d.description)
|
||||
hash := md5.Sum([]byte(encoded))
|
||||
d.id = hex.EncodeToString(hash[:])
|
||||
|
||||
return d.id, nil
|
||||
}
|
||||
|
||||
// Description returns the diagram description.
|
||||
func (d *Diagram) Description() []byte {
|
||||
return d.description
|
||||
}
|
||||
|
||||
// Description returns the diagram description.
|
||||
func (d *Diagram) WithDescription(description []byte) *Diagram {
|
||||
d.description = description
|
||||
d.id = ""
|
||||
return d
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Generator provides the ability to generate a diagram.
|
||||
type Generator interface {
|
||||
// Generate generates the given diagram.
|
||||
Generate(diagram *Diagram) error
|
||||
}
|
||||
|
||||
func NewGenerator(cache DiagramCache, mermaidCLIPath string, inPath string, outPath string) Generator {
|
||||
return &cachingGenerator{
|
||||
cache: cache,
|
||||
mermaidCLIPath: mermaidCLIPath,
|
||||
inPath: inPath,
|
||||
outPath: outPath,
|
||||
}
|
||||
}
|
||||
|
||||
// cachingGenerator is an implementation of Generator.
|
||||
type cachingGenerator struct {
|
||||
cache DiagramCache
|
||||
mermaidCLIPath string
|
||||
inPath string
|
||||
outPath string
|
||||
}
|
||||
|
||||
// Generate generates the given diagram.
|
||||
func (c cachingGenerator) Generate(diagram *Diagram) error {
|
||||
has, err := c.cache.Has(diagram)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if has {
|
||||
cached, err := c.cache.Get(diagram)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*diagram = *cached
|
||||
return nil
|
||||
}
|
||||
if err := c.generate(diagram); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := c.cache.Store(diagram); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generate does the actual file generation.
|
||||
func (c cachingGenerator) generate(diagram *Diagram) error {
|
||||
id, err := diagram.ID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
has, err := c.cache.Has(diagram)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if has {
|
||||
cached, err := c.cache.Get(diagram)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*diagram = *cached
|
||||
return nil
|
||||
}
|
||||
|
||||
inPath := fmt.Sprintf("%s/%s.mmd", c.inPath, id)
|
||||
outPath := fmt.Sprintf("%s/%s.svg", c.outPath, id)
|
||||
|
||||
if err := ioutil.WriteFile(inPath, diagram.description, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.Command(c.mermaidCLIPath, "-i", inPath, "-o", outPath)
|
||||
var stdOut bytes.Buffer
|
||||
cmd.Stdout = bufio.NewWriter(&stdOut)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("%w: %s", err, string(stdOut.Bytes()))
|
||||
}
|
||||
|
||||
diagram.Output = outPath
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func writeJSON(rw http.ResponseWriter, value interface{}, status int) {
|
||||
bytes, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
panic("could not marshal value: " + err.Error())
|
||||
}
|
||||
rw.Header().Set("Content-Type", "application/json")
|
||||
rw.WriteHeader(status)
|
||||
if _, err := rw.Write(bytes); err != nil {
|
||||
panic("could not write bytes to response: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func writeSVG(rw http.ResponseWriter, data []byte, status int) {
|
||||
rw.Header().Set("Content-Type", "image/svg+xml")
|
||||
rw.WriteHeader(status)
|
||||
if _, err := rw.Write(data); err != nil {
|
||||
panic("could not write bytes to response: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func writeErr(rw http.ResponseWriter, err error, status int) {
|
||||
writeJSON(rw, map[string]interface{}{
|
||||
"error": err,
|
||||
}, status)
|
||||
}
|
||||
|
||||
func GenerateHTTPHandler(generator Generator) func(rw http.ResponseWriter, r *http.Request) {
|
||||
return func(rw http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
writeErr(rw, fmt.Errorf("expected HTTP method POST"), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
// Get description from request body
|
||||
bytes, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
writeErr(rw, fmt.Errorf("could not read body: %s", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Create a diagram from the description
|
||||
d := NewDiagram(bytes)
|
||||
|
||||
// Generate the diagram
|
||||
if err := generator.Generate(d); err != nil {
|
||||
writeErr(rw, fmt.Errorf("could not generate diagram: %s", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Output the diagram as an SVG.
|
||||
// We assume generate always generates an SVG at this point in time.
|
||||
diagramBytes, err := ioutil.ReadFile(d.Output)
|
||||
if err != nil {
|
||||
writeErr(rw, fmt.Errorf("could not read diagram bytes: %s", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeSVG(rw, diagramBytes, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,381 @@
|
|||
{
|
||||
"name": "mermaid-server-cli",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@mermaid-js/mermaid-cli": {
|
||||
"version": "8.4.8",
|
||||
"resolved": "https://registry.npmjs.org/@mermaid-js/mermaid-cli/-/mermaid-cli-8.4.8.tgz",
|
||||
"integrity": "sha512-25Ichye2lpNso9Dylrm5a+SJWZ5rpuPxVw1OVdcl9ZoTDGxdE3AyTfcCjoT5oKVfDUd+Uu2ONUsfJBtw42I8uw==",
|
||||
"requires": {
|
||||
"chalk": "^3.0.0",
|
||||
"commander": "^4.0.1",
|
||||
"puppeteer": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@types/color-name": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
|
||||
},
|
||||
"@types/mime-types": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz",
|
||||
"integrity": "sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM="
|
||||
},
|
||||
"agent-base": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz",
|
||||
"integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
|
||||
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
|
||||
"requires": {
|
||||
"@types/color-name": "^1.1.1",
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
|
||||
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||
},
|
||||
"chalk": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"commander": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"concat-stream": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^2.2.2",
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"extract-zip": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
|
||||
"integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==",
|
||||
"requires": {
|
||||
"concat-stream": "^1.6.2",
|
||||
"debug": "^2.6.9",
|
||||
"mkdirp": "^0.5.4",
|
||||
"yauzl": "^2.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"fd-slicer": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||
"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
|
||||
"requires": {
|
||||
"pend": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz",
|
||||
"integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==",
|
||||
"requires": {
|
||||
"agent-base": "5",
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"mime": {
|
||||
"version": "2.4.4",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
|
||||
"integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.43.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
|
||||
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.26",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
|
||||
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
|
||||
"requires": {
|
||||
"mime-db": "1.43.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"puppeteer": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-2.1.1.tgz",
|
||||
"integrity": "sha512-LWzaDVQkk1EPiuYeTOj+CZRIjda4k2s5w4MK4xoH2+kgWV/SDlkYHmxatDdtYrciHUKSXTsGgPgPP8ILVdBsxg==",
|
||||
"requires": {
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"debug": "^4.1.0",
|
||||
"extract-zip": "^1.6.6",
|
||||
"https-proxy-agent": "^4.0.0",
|
||||
"mime": "^2.0.3",
|
||||
"mime-types": "^2.1.25",
|
||||
"progress": "^2.0.1",
|
||||
"proxy-from-env": "^1.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"ws": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
||||
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"typedarray": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"ws": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||
"requires": {
|
||||
"async-limiter": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"yauzl": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
|
||||
"integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
|
||||
"requires": {
|
||||
"buffer-crc32": "~0.2.3",
|
||||
"fd-slicer": "~1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "mermaid-server-cli",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@mermaid-js/mermaid-cli": "^8.4.8"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue