diff --git a/.gitignore b/.gitignore index 3a57359b9..02975b8ac 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,31 @@ env.yaml domain-key.txt domain-crt.txt +### Node ### +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* +yarn.lock +package.json +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* +pids +*.pid +*.seed +*.pid.lock +web_modules/ +node_modules/ +jspm_packages/ +.npm +.node_repl_history + ### Haskell ### dist dist-* diff --git a/fission-web-api/library/Fission/Web/API/Types.hs b/fission-web-api/library/Fission/Web/API/Types.hs index 6eeb0e924..0bff3da06 100644 --- a/fission-web-api/library/Fission/Web/API/Types.hs +++ b/fission-web-api/library/Fission/Web/API/Types.hs @@ -39,20 +39,20 @@ data RoutesV2 mode = RoutesV2 deriving Generic data V2 mode = V2 - { ipfs :: mode :- "ipfs" :> ToServantApi IPFS.RoutesV2 - , app :: mode :- "app" :> ToServantApi App.RoutesV2 - , user :: mode :- "user" :> ToServantApi User.RoutesV2 - , auth :: mode :- "auth" :> "ucan" :> ToServantApi UCAN.Routes + { ipfs :: mode :- "ipfs" :> ToServantApi IPFS.RoutesV2 + , app :: mode :- "app" :> ToServantApi App.RoutesV2 + , user :: mode :- "user" :> ToServantApi User.RoutesV2 + , auth :: mode :- "auth" :> "ucan" :> ToServantApi UCAN.Routes } deriving Generic -- DEPRECATED version data RoutesV_ mode = RoutesV_ - { ipfs :: mode :- "ipfs" :> ToServantApi IPFS.RoutesV_ - , app :: mode :- "app" :> ToServantApi App.RoutesV_ - , user :: mode :- "user" :> ToServantApi User.RoutesV_ - , dns :: mode :- "dns" :> ToServantApi DNS.Routes - , auth :: mode :- "auth" :> "ucan" :> ToServantApi UCAN.Routes + { ipfs :: mode :- "ipfs" :> ToServantApi IPFS.RoutesV_ + , app :: mode :- "app" :> ToServantApi App.RoutesV_ + , user :: mode :- "user" :> ToServantApi User.RoutesV_ + , dns :: mode :- "dns" :> ToServantApi DNS.Routes + , auth :: mode :- "auth" :> "ucan" :> ToServantApi UCAN.Routes , ping :: mode diff --git a/fission-web-api/library/Fission/Web/API/User/Types.hs b/fission-web-api/library/Fission/Web/API/User/Types.hs index 7797e2090..94779c25e 100644 --- a/fission-web-api/library/Fission/Web/API/User/Types.hs +++ b/fission-web-api/library/Fission/Web/API/User/Types.hs @@ -13,24 +13,24 @@ import Fission.Web.API.User.Verify.Types import qualified Fission.Web.API.User.WhoAmI.Types as WhoAmI data RoutesV2 mode = RoutesV2 - { create :: mode :- Create.WithDID - , dataRoot :: mode :- "data" :> ToServantApi DataRoot.RoutesV2 - , email :: mode :- "email" :> ToServantApi Email.Routes - , did :: mode :- "did" :> ToServantApi DID.Routes - , whoAmI :: mode :- "whoami" :> ToServantApi WhoAmI.Routes - , linkingRelay :: mode :- "user" :> "link" :> ToServantApi Relay.Routes + { dataRoot :: mode :- "data" :> ToServantApi DataRoot.RoutesV2 + , email :: mode :- "email" :> ToServantApi Email.Routes + , did :: mode :- "did" :> ToServantApi DID.Routes + , whoAmI :: mode :- "whoami" :> ToServantApi WhoAmI.Routes + , linkingRelay :: mode :- "link" :> ToServantApi Relay.Routes + , create :: mode :- Create.WithDID } deriving Generic data RoutesV_ mode = RoutesV_ - { create :: mode :- ToServantApi Create.RoutesV_ - , whoAmI :: mode :- ToServantApi WhoAmI.Routes + { whoAmI :: mode :- "whoami" :> ToServantApi WhoAmI.Routes , email :: mode :- "email" :> ToServantApi Email.Routes , did :: mode :- "did" :> ToServantApi DID.Routes , exchangeKeys :: mode :- "exchange" :> "keys" :> ToServantApi ExchangeKeys.Routes - , linkingRelay :: mode :- "user" :> "link" :> ToServantApi Relay.Routes + , linkingRelay :: mode :- "link" :> ToServantApi Relay.Routes , dataRoot :: mode :- "data" :> ToServantApi DataRoot.RoutesV_ , passwordReset :: mode :- Password.Reset , verify :: mode :- Verify + , create :: mode :- ToServantApi Create.RoutesV_ } deriving Generic diff --git a/fission-web-api/package.yaml b/fission-web-api/package.yaml index fa14b22b6..c52378283 100644 --- a/fission-web-api/package.yaml +++ b/fission-web-api/package.yaml @@ -1,5 +1,5 @@ name: fission-web-api -version: '2.0.0.0' +version: '2.0.1.0' category: API author: - Brooklyn Zelenka diff --git a/fission-web-server/library/Fission/Web/Server.hs b/fission-web-server/library/Fission/Web/Server.hs index 1b34d54eb..6bd2136d8 100644 --- a/fission-web-server/library/Fission/Web/Server.hs +++ b/fission-web-server/library/Fission/Web/Server.hs @@ -171,4 +171,4 @@ server appHost = } v2Docs = - Web.Swagger.handler fromHandler appHost Fission.version (Proxy @(ToServantApi Fission.RoutesV2)) + Web.Swagger.handler fromHandler appHost Fission.version (Proxy @("v2" :> (ToServantApi Fission.RoutesV2))) diff --git a/fission-web-server/package.yaml b/fission-web-server/package.yaml index e28354536..b4b24c4b2 100644 --- a/fission-web-server/package.yaml +++ b/fission-web-server/package.yaml @@ -1,5 +1,5 @@ name: fission-web-server -version: '2.16.0.0' +version: '2.16.1.0' category: API author: - Brooklyn Zelenka diff --git a/rosetta.nix b/rosetta.nix deleted file mode 100644 index 658ec38bf..000000000 --- a/rosetta.nix +++ /dev/null @@ -1,79 +0,0 @@ -let - sources = import ./nix/sources.nix; - commands = import ./nix/commands.nix; - - nixos = import sources.nixos { system = "x86_64-darwin"; }; - darwin = import sources.darwin { system = "x86_64-darwin"; }; - unstable = import sources.unstable { system = "x86_64-darwin"; }; - - pkgs = if darwin.stdenv.isDarwin then darwin else nixos; - tasks = commands { - inherit pkgs; - inherit unstable; - inherit server-path; - inherit server-port; - }; - - server-path = "~/.local/bin/fission-server"; - server-port = 10235; - - deps = { - bench = [pkgs.wrk2]; - - common = [ - pkgs.gnumake - unstable.niv - ]; - - crypto = [ - pkgs.openssl.dev - pkgs.openssl.out - ]; - - cli = [pkgs.ncurses.dev.out]; - - data = [ - pkgs.ipfs - pkgs.lzma.dev - pkgs.lzma.out - pkgs.zlib.dev - pkgs.zlib.out - pkgs.postgresql - ]; - - haskell = [ - unstable.ghc - unstable.haskellPackages.implicit-hie - unstable.haskell-language-server - unstable.stack - unstable.stylish-haskell - ]; - - macos = - if pkgs.stdenv.isDarwin then - [ unstable.darwin.apple_sdk.frameworks.CoreServices - unstable.darwin.apple_sdk.frameworks.Foundation - unstable.darwin.apple_sdk.frameworks.Cocoa - ] - else - []; - }; -in - -unstable.haskell.lib.buildStackProject { - name = "Fission"; - nativeBuildInputs = builtins.concatLists [ - deps.common - deps.crypto - deps.cli - deps.data - deps.macos - deps.haskell - tasks - ]; - - shellHook = '' - export LANG=C.UTF8 - echo "⚠️ Remember to override the nix.shell-path in stack.yaml ⚠️ " - ''; -} diff --git a/shell.nix b/shell.nix index eaf36b605..9aa4ac435 100644 --- a/shell.nix +++ b/shell.nix @@ -1,31 +1,32 @@ -let - sources = import ./nix/sources.nix; - commands = import ./nix/commands.nix; +{ rosetta ? false }: + let + sources = import ./nix/sources.nix; + commands = import ./nix/commands.nix; - nixos = import sources.nixos {}; - darwin = import sources.darwin {}; - unstable = import sources.unstable {}; + overrides = if rosetta then { system = "x86_64-darwin"; } else {}; - pkgs = if darwin.stdenv.isDarwin then darwin else nixos; - tasks = commands { - inherit pkgs; - inherit unstable; - inherit server-path; - inherit server-port; - }; + nixos = import sources.nixos overrides; + darwin = import sources.darwin overrides; + unstable = import sources.unstable overrides; - server-path = "~/.local/bin/fission-server"; - server-port = 10235; + pkgs = if darwin.stdenv.isDarwin then darwin else nixos; + tasks = commands { + inherit pkgs; + inherit unstable; + inherit server-path; + inherit server-port; + }; - deps = { - bench = [pkgs.wrk2]; + server-path = "~/.local/bin/fission-server"; + server-port = 10235; - common = [ - pkgs.gnumake - unstable.niv - ]; + deps = { + common = [ + pkgs.gnumake + unstable.niv + ]; - crypto = [ + crypto = [ pkgs.openssl.dev pkgs.openssl.out ]; @@ -34,7 +35,7 @@ let data = [ pkgs.ipfs - pkgs.lzma.dev + pkgs.lzma.dev pkgs.lzma.out pkgs.zlib.dev pkgs.zlib.out @@ -55,24 +56,24 @@ let unstable.darwin.apple_sdk.frameworks.Foundation unstable.darwin.apple_sdk.frameworks.Cocoa ] - else + else []; }; -in -unstable.haskell.lib.buildStackProject { - name = "Fission"; - nativeBuildInputs = builtins.concatLists [ - deps.common - deps.crypto - deps.cli - deps.data - deps.macos - deps.haskell - tasks - ]; + in + unstable.haskell.lib.buildStackProject { + name = "Fission"; + nativeBuildInputs = builtins.concatLists [ + deps.common + deps.crypto + deps.cli + deps.data + deps.macos + deps.haskell + tasks + ]; - shellHook = '' - export LANG=C.UTF8 - ''; -} + shellHook = '' + export LANG=C.UTF8 + ''; + } diff --git a/stack.yaml b/stack.yaml index ab0cb0195..a57d54dfd 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: lts-18.9 +resolver: lts-18.10 allow-newer: true packages: @@ -35,4 +35,4 @@ ghc-options: nix: enable: true pure: true - shell-file: rosetta.nix + shell-file: shell.nix diff --git a/stack.yaml.lock b/stack.yaml.lock index 2cf7fff4d..73cd9d3d6 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -125,7 +125,7 @@ packages: hackage: http-link-header-1.0.3.1 snapshots: - completed: - size: 586923 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/9.yaml - sha256: 9f9fe35c949414146840a985fb228fd397c504d1781b834bfc9ab935f4d27df6 - original: lts-18.9 + size: 587546 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/10.yaml + sha256: 88b4f81e162ba3adc230a9fcccc4d19ac116377656bab56c7382ca88598b257a + original: lts-18.10 diff --git a/swagger_snapshots/fission-web-api-1.3.0.0/v_.json b/swagger_snapshots/fission-web-api-1.3.0.0/v_.json new file mode 100644 index 000000000..0024daae0 --- /dev/null +++ b/swagger_snapshots/fission-web-api-1.3.0.0/v_.json @@ -0,0 +1 @@ +{"openapi":"3.0.1","info":{"title":"The Fission API","description":"Bootstrapped & distributed backend-as-a-service with user-controlled data","contact":{"name":"Team Fission","url":"https://fission.codes","email":"support@fission.codes"},"license":{"name":"AGPL 3.0","url":"https://www.gnu.org/licenses/agpl-3.0.en.html"},"version":"2.15.1.0"},"servers":[{"url":"https://runfission.com/"}],"tags":[{"name":"App","description":"Hosted applications"},{"name":"Auth","description":"Specialized auth endpoints"},{"name":"DNS","description":"DNS management"},{"name":"Heroku","description":"Interaction with the Heroku add-on API"},{"name":"IPFS","description":"The primary IPFS API"},{"name":"Ping","description":"Check for liveness"},{"name":"User","description":"Accounts, authentication, and stats"}],"paths":{"/user/whoami":{"get":{"tags":["User"],"summary":"Get username","description":"Get username registered to currently authenticated user","responses":{"200":{"description":"","content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Username"}},"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Username"}}}}}}},"/ipfs/{cid}":{"get":{"tags":["IPFS"],"summary":"Get a file (path)","description":"Download a file by its CID","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/octet-stream":{"schema":{"$ref":"#/components/schemas/SerializedFile"}},"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/SerializedFile"}}}},"404":{"description":"`cid` not found","content":{}}}},"put":{"tags":["IPFS"],"summary":"Pin CID","description":"DEPRECATED ⛔ Pin an otherwise unassociated CID","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{}},"404":{"description":"`cid` not found","content":{}}}},"delete":{"tags":["IPFS"],"summary":"Unpin CID","description":"DEPRECATED ⛔ Unpin an otherwise unassociated CID","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{}},"404":{"description":"`cid` not found","content":{}}}}},"/user/reset_password":{"put":{"tags":["User"],"summary":"Reset password","description":"DEPRECATED ⛔ Reset password","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/PasswordResetRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Password"}}}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/user/data/{newCID}":{"patch":{"tags":["User"],"summary":"Update data root","description":"Set/update currently authenticated user's file system content","parameters":[{"name":"newCID","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`newCID` not found","content":{}}}}},"/user/did/{Username}/{Challenge}":{"put":{"tags":["User"],"summary":"Update Public Key via Email Challenge","description":"Set given username's public key to something else via providing a challenge obtained from /user/email/recover","parameters":[{"name":"Username","in":"path","required":true,"schema":{"type":"string"}},{"name":"Challenge","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/PublicKey"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}},"404":{"description":"`Username` or `Challenge` not found","content":{}}},"x-codegen-request-body-name":"body"}},"/ipfs":{"get":{"tags":["IPFS"],"summary":"Get a file (query param)","description":"Download a file by its CID","parameters":[{"name":"cid","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/octet-stream":{"schema":{"$ref":"#/components/schemas/SerializedFile"}},"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/SerializedFile"}}}},"400":{"description":"Invalid `cid`","content":{}}}},"post":{"tags":["IPFS"],"summary":"Upload file","description":"Directly upload a file over HTTP","requestBody":{"content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/SerializedFile"}},"application/octet-stream":{"schema":{"$ref":"#/components/schemas/SerializedFile"}}},"required":true},"responses":{"200":{"description":"","content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}},"application/octet-stream":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}}}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/app/{App URL}/{New CID}":{"patch":{"tags":["App"],"summary":"Set app content","description":"Update the content (CID) for an app","parameters":[{"name":"App URL","in":"path","required":true,"schema":{"type":"string"}},{"name":"New CID","in":"path","required":true,"schema":{"type":"string"}},{"name":"copy-data","in":"query","schema":{"type":"boolean"}}],"responses":{"202":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"maxItems":0,"type":"array","example":[],"items":{"type":"object"}}}}},"400":{"description":"Invalid `copy-data`","content":{}},"404":{"description":"`App URL` or `New CID` not found","content":{}}}}},"/user":{"put":{"tags":["User"],"summary":"Create user with DID and UCAN proof","description":"Register a new user (must auth with user-controlled DID)","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Registration"}}},"required":true},"responses":{"201":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"},"post":{"tags":["User"],"summary":"Create user with password","description":"DEPRECATED ⛔ Register a new user (must auth with user-controlled DID)","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Registration"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"maxItems":0,"type":"array","example":[],"items":{"type":"object"}}}}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/auth/ucan":{"post":{"tags":["Auth"],"summary":"Verify a UCAN","description":"Check if a UCAN is validly formatted","parameters":[{"name":"ignore_time","in":"query","allowEmptyValue":true,"schema":{"type":"boolean","default":false}}],"requestBody":{"content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/BareUCAN"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `ignore_time` or `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/user/email/resend":{"post":{"tags":["User"],"summary":"Resend verification email","description":"Send a verification email to currently authenticated user.","responses":{"204":{"description":"","content":{}}}}},"/heroku/resources/{addon_id}":{"delete":{"tags":["Heroku"],"summary":"Deprovision","description":"Deprovision a Heroku add-on (for the Heroku partner service only)","parameters":[{"name":"addon_id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"","content":{}},"404":{"description":"`addon_id` not found","content":{}}}}},"/user/email/verify/{Challenge}":{"get":{"tags":["User"],"summary":"Email verification","parameters":[{"name":"Challenge","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`Challenge` not found","content":{}}}}},"/ping":{"get":{"tags":["Ping"],"summary":"Simple Ping","description":"A quick way to check for liveness","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Pong"}},"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Pong"}}}}}}},"/heroku/resources":{"post":{"tags":["Heroku"],"summary":"Provision","description":"Provision a new Heroku add-on (for the Heroku partner service only)","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/ProvisionRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/vnd.heroku-addons+json;version=3":{"schema":{"$ref":"#/components/schemas/UserProvisionResponse"}}}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/user/email/recover/{Username}":{"post":{"tags":["User"],"summary":"Email verification for account recovery","parameters":[{"name":"Username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`Username` not found","content":{}}}}},"/ipfs/peers":{"get":{"tags":["IPFS"],"summary":"Peer index","description":"List of recommended IPFS peers","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}},"text/plain;charset=utf-8":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}},"application/octet-stream":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}}}}}}},"/user/did":{"put":{"tags":["User"],"summary":"Update Public Key","description":"Set currently authenticated user's root public key to another one","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/PublicKey"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/app/{appId}":{"delete":{"tags":["App"],"summary":"Destroy app by ID","description":"Destroy app by its ID","parameters":[{"name":"appId","in":"path","required":true,"schema":{"minimum":0,"exclusiveMinimum":false,"type":"integer"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`appId` not found","content":{}}}}},"/app/associated/{url}":{"delete":{"tags":["App"],"summary":"Destroy app by URL","description":"Destroy app by any associated URL","parameters":[{"name":"url","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`url` not found","content":{}}}}},"/user/data/{username}":{"get":{"tags":["User"],"summary":"Get Data Root","description":"Retrieve a user's data root from DNS","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}},"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}}}},"404":{"description":"`username` not found","content":{}}}}},"/user/verify":{"get":{"tags":["User"],"summary":"Validate auth","description":"DEPRECATED ⛔ Verify user auth -- prefer /user/whoami","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"type":"boolean"}}}}}}},"/ipfs/dag":{"post":{"tags":["IPFS"],"summary":"Pin an IPFS DAG structure","description":"Pin some data not associated to a user app or file system. We call these loose pins, likely to be deprecated.","requestBody":{"content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/SerializedFile"}},"application/octet-stream":{"schema":{"$ref":"#/components/schemas/SerializedFile"}}},"required":true},"responses":{"200":{"description":"","content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}},"application/octet-stream":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}}}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/app":{"get":{"tags":["App"],"summary":"App index","description":"A list of all of your apps and their associated domain names","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/App Index Payload"}}}}}}},"post":{"tags":["App"],"summary":"Create app","description":"Creates a new app, assigns an initial subdomain, and sets an asset placeholder","parameters":[{"name":"subdomain","in":"query","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/URL"}}}},"400":{"description":"Invalid `subdomain`","content":{}}}}},"/dns/{cid}":{"put":{"tags":["DNS"],"summary":"Set account's DNSLink","description":"DEPRECATED ⛔ Set account's DNSLink to a CID","parameters":[{"name":"cid","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/DomainName"}},"application/octet-stream":{"schema":{"$ref":"#/components/schemas/DomainName"}}}},"404":{"description":"`cid` not found","content":{}}}}},"/user/exchange/keys/{did}":{"put":{"tags":["User"],"summary":"Add Public Exchange Key","description":"Add a key to the currently authenticated user's root list of public exchange keys","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/RSA.PublicKey"}}}}},"404":{"description":"`did` not found","content":{}}}},"delete":{"tags":["User"],"summary":"Remove Public Exchange Key","description":"Remove a key from the currently authenticated user's root list of public exchange keys","parameters":[{"name":"did","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RSA.PublicKey"}}}}},"404":{"description":"`did` not found","content":{}}}}},"/ipfs/cids":{"get":{"tags":["IPFS"],"summary":"CID Index","description":"List of all of your pinned CIDs (not associated with your personal file system or apps)","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IPFSAddress"}}},"text/plain;charset=utf-8":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/IPFSAddress"}}}}}}}}},"components":{"schemas":{"IPFSAddress":{"type":"string","example":"QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ"},"BareUCAN":{"type":"string","description":"An encoded UCAN (JWT) *without* a 'bearer' header tag","example":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVhdiI6IjAuMS4wIn0.eyJhdWQiOiJkaWQ6a2V5OnpTdEVacHpTTXRUdDlrMnZzemd2Q3dGNGZMUVFTeUExNVc1QVE0ejNBUjZCeDRlRko1Y3JKRmJ1R3hLbWJtYTQiLCJleHAiOjE1OTE2Mjc4NDEsImlzcyI6ImRpZDprZXk6ejEzVjNTb2cyWWFVS2hkR0NtZ3g5VVp1VzFvMVNoRkpZYzZEdkdZZTdOVHQ2ODlOb0wzazdIdXdCUXhKZFBqdllURHhFd3kxbTh3YjZwOTRjNm1NWTRmTnFBV0RkeVk3NVNWMnFEODVLNU1ZcVpqYUpZOGM0NzFBUEZydkpTZEo1QXo1REVDaENnV0xOdkVYRjJxaFlSMkZWaVprVGhvRVB0Mk5ZcHVxZ0txZVZvS1RpZkRpd3JYeUhka3hCazJNOWNQZE5HaGczRE0xWTZyVGY2RDJIZ2JlUnF2OGtvVW9xeWlLTWpYYUZTZlFZVkY3cGZGWGhOYWdKRGZqcG9xQ3FWWFllaTFQbU43UzM0cFdvcTZwUmRQczY5N2F4VVRFNXZQeXNlU3ROc3o4SGFqdUp2NzlDSENNZ2RvRkJzOXc3UHZNSFVEeGdHUWR0c3hBQXZKRzRxVGJkU0I2bUd2TFp0cGE5czFNemNIcDVEV1NjaUJxNnF1aG1SSHRTVFdHNW9FSnRTdlN4QlhTczJoZFBId0I0QVUiLCJuYmYiOjE1OTE2Mjc3NTEsInByZiI6ImV5SmhiR2NpT2lKU1V6STFOaUlzSW5SNWNDSTZJa3BYVkNJc0luVmhkaUk2SWpBdU1TNHdJbjAuZXlKaGRXUWlPaUprYVdRNmEyVjVPbm94TTFZelUyOW5NbGxoVlV0b1pFZERiV2Q0T1ZWYWRWY3hiekZUYUVaS1dXTTJSSFpIV1dVM1RsUjBOamc1VG05TU0yczNTSFYzUWxGNFNtUlFhblpaVkVSNFJYZDVNVzA0ZDJJMmNEazBZelp0VFZrMFprNXhRVmRFWkhsWk56VlRWakp4UkRnMVN6Vk5XWEZhYW1GS1dUaGpORGN4UVZCR2NuWktVMlJLTlVGNk5VUkZRMmhEWjFkTVRuWkZXRVl5Y1doWlVqSkdWbWxhYTFSb2IwVlFkREpPV1hCMWNXZExjV1ZXYjB0VWFXWkVhWGR5V0hsSVpHdDRRbXN5VFRsalVHUk9SMmhuTTBSTk1WazJjbFJtTmtReVNHZGlaVkp4ZGpocmIxVnZjWGxwUzAxcVdHRkdVMlpSV1ZaR04zQm1SbGhvVG1GblNrUm1hbkJ2Y1VOeFZsaFpaV2t4VUcxT04xTXpOSEJYYjNFMmNGSmtVSE0yT1RkaGVGVlVSVFYyVUhselpWTjBUbk42T0VoaGFuVktkamM1UTBoRFRXZGtiMFpDY3psM04xQjJUVWhWUkhoblIxRmtkSE40UVVGMlNrYzBjVlJpWkZOQ05tMUhka3hhZEhCaE9YTXhUWHBqU0hBMVJGZFRZMmxDY1RaeGRXaHRVa2gwVTFSWFJ6VnZSVXAwVTNaVGVFSllVM015YUdSUVNIZENORUZWSWl3aVpYaHdJam94TlRrME1qRTVOelE0TENKcGMzTWlPaUprYVdRNmEyVjVPbm94TTFZelUyOW5NbGxoVlV0b1pFZERiV2Q0T1ZWYWRWY3hiekZUYUVaS1dXTTJSSFpIV1dVM1RsUjBOamc1VG05TU0wWjFRVlIwVlZCV1p6ZHBXRGQ0YlUxdGNrbzJNVE0wVkcxaE1tSkdWWE5YVVhreVRtUkhTREZYYVRSSWVVNWhOemh3VG0xU1RrRkdVRWhHU21KcVNqRnhZemc0TkZoeE1XbHlhV2wwY1ZKVk0zQmtkRVJSVFhobmIyRjNNVUptVFZkRlRVWnJkVmxWUm5Gd1JFdGlSMHd6WTNKQ2VtNUxkbFpNZDJsRGExQkhiM2h0V0VGWE4waFZOemw2TmxCVVRVZDVVMHRDUlVGMVdERjNSVE0wTlRKQ05rbzVOblphZFc5aVJUTlpZVUV5T0hsTFMwaE1OV2xxWmtKVVJFVTFaRTF6TmpWaFJraGlSbVZUZDNONlJtMWxkVkZxTkdkS1JEVklaMUJOYjI1bGRHZzNUSFZIWlhVMFlWVldWMFZDVkZKdk5sWmlTbFpRTVdKSVNqZHhUbUZRWW1JMFNrUjRTa2hFUkhaeFV6Vm9PRlJCZFZVMmIweFNUa1ZuTTJSdU4xSnBjV295VW1ST1ZYbFRkbkZxVkU0MWQzUk1VMjl3ZGtSNlFVSXllbFl5VUhSYWNETjJNVEZPYjJaRWEyNTJSWFpYYTBONmRYbFdRVnA1VFVGbk9HZGFXa2RESWl3aWJtSm1Jam94TlRreE5qSTNOamc0TENKd2RHTWlPaUpCVUZCRlRrUWlMQ0p6WTNBaU9pSXZJbjAuZWFIcmZuaFJkdy1ob1B3Q2RjVXpTX09abm5VXzFIR3RwU0JHenM1SmtDcGs5RlVQZVYwU2xVbF9kUkI0UzZ0M2xnbi14UHVoaVA3WE5kMGM3Qm9hZFd0SkxMSlY4VV9MZ2pUUUdMa1h4al9yVTZrYXA4bFRibllneDZPZzFiZi10bUhlVVVCNFZOY2RFUGlTMFRUYllMZlFDN05rLTZzbWkwekNYQlVBd1JrLURSQURtdkdhMzloVzFMQlFqWl9oejVhOVRYTTlRb0drS0szQkxDM2JVbXFKU1Y0SjVCTmlxanQ0TktqOUo1RjVYYjdHNTd4MkttWkVMYUw1U2NYV1lvWmpxVlJNWF9MY3k1WE4xaUJvWmFHVHlFbzlVNVBNYzhRSVRoaEdQTXNtc2JTS1cxc1AyUFF6OGNOUHh5b2NXYmZsT0dQZkVGZ21aenk4RGwxTkN3IiwicHRjIjoiQVBQRU5EIiwic2NwIjoiLyJ9"},"UUID":{"type":"string","format":"uuid","example":"00000000-0000-0000-0000-000000000000"},"PasswordResetRequest":{"type":"object","properties":{"password":{"type":"string"}},"description":"Password Reset Request"},"UserProvisionResponse":{"required":["config","id"],"type":"object","properties":{"config":{"$ref":"#/components/schemas/UserConfig"},"id":{"minimum":0,"exclusiveMinimum":false,"type":"integer"},"message":{"type":"string"},"peers":{"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}},"description":"Provisioned user login information","example":{"config":{"INTERPLANETARY_FISSION_PASSWORD":"GW0SHByPmY0.y+lg)x7De.PNmJvh1","INTERPLANETARY_FISSION_USERNAME":"c74bd95b8555275277d4","INTERPLANETARY_FISSION_URL":"https://runfission.com"},"id":4213,"message":"Provisioned successfully"}},"URL":{"type":"string","description":"A domain name, potentially with a subdomain","example":"foo.example.com"},"UserConfig":{"type":"object","properties":{"INTERPLANETARY_FISSION_PASSWORD":{"$ref":"#/components/schemas/Secret"},"INTERPLANETARY_FISSION_USERNAME":{"type":"string"},"INTERPLANETARY_FISSION_URL":{"$ref":"#/components/schemas/BaseUrl"}},"description":"The information that a user needs to know to access this service. Typically sent on provision","example":{"INTERPLANETARY_FISSION_PASSWORD":"GW0SHByPmY0.y+lg)x7De.PNmJvh1","INTERPLANETARY_FISSION_USERNAME":"c74bd95b8555275277d4","INTERPLANETARY_FISSION_URL":"https://runfission.com"}},"BaseUrl":{"type":"string","example":"https://runfission.com"},"HerokuRegion":{"type":"string","description":"The Heroku hosted region where the user's data is hoted","example":"amazon-web-services::ap-northeast-1"},"PublicKey":{"type":"string","description":"A public key"},"Secret":{"type":"string","description":"User secret (used for authentication)","example":"U)mRvIvI6$L_MkYpme!lfzMte_92M5G912-NUfRmfxhRKx$Rr6aLUxqdqW"},"IPFSPeer":{"type":"string","description":"An IPFS peer address","example":"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd"},"Username":{"type":"string","example":"username"},"SerializedFile":{"type":"string","description":"A typical file's contents","example":"hello world"},"DomainName":{"type":"string","description":"A domain name","example":"myawesomedomain.com"},"Password":{"required":["password"],"type":"object","properties":{"password":{"type":"string"}}},"UTCTime":{"type":"string","format":"yyyy-mm-ddThh:MM:ssZ","example":"2016-07-22T00:00:00Z"},"Tier":{"type":"string","enum":["test","free"]},"ProvisionRequest":{"title":"Heroku Provisioning Request","required":["callbackUrl","name","plan","region","uuid"],"type":"object","properties":{"callbackUrl":{"type":"string"},"uuid":{"$ref":"#/components/schemas/UUID"},"plan":{"$ref":"#/components/schemas/Tier"},"name":{"type":"string"},"region":{"$ref":"#/components/schemas/HerokuRegion"}},"description":"Request from Heroku to provision a new user","example":{"uuid":"0cebfcfe-93c9-11e9-bc42-526af7764f64","plan":"free","name":"my-awesome-app","callback_url":"callback.herokuapp.com/foo","region":"amazon-web-services::ap-northeast-1"}},"RSA.PublicKey":{"type":"string","description":"An RSA public key"},"Pong":{"type":"string","description":"A simple response","example":"pong"},"App Index Payload":{"required":["insertedAt","modifiedAt","urls"],"type":"object","properties":{"modifiedAt":{"$ref":"#/components/schemas/UTCTime"},"urls":{"type":"array","items":{"$ref":"#/components/schemas/URL"}},"insertedAt":{"$ref":"#/components/schemas/UTCTime"}},"description":"Properties for a registered application","example":{"modifiedAt":"2021-05-10T01:26:40Z","urls":["my-cool-subdomain.fission.codes"],"insertedAt":"2021-05-09T22:40:00Z"}},"Registration":{"required":["email","username"],"type":"object","properties":{"email":{"type":"string"},"username":{"type":"string"}},"description":"The information that a user needs to provide to login/register.","example":{"email":"alice@example.com","username":"username"}}},"securitySchemes":{"Fission Auth":{"type":"apiKey","description":"A higher-order auth type that accepts both Basic Auth and Fission-formatted JWTs as described here: https://whitepaper.fission.codes/identity/authentication","name":"Authorization","in":"header"},"basic":{"type":"http","scheme":"basic"}}}} \ No newline at end of file diff --git a/swagger_snapshots/fission-web-api-2.0.1.0/v2.json b/swagger_snapshots/fission-web-api-2.0.1.0/v2.json new file mode 100644 index 000000000..9ac19305a --- /dev/null +++ b/swagger_snapshots/fission-web-api-2.0.1.0/v2.json @@ -0,0 +1 @@ +{"openapi":"3.0.1","info":{"title":"The Fission API","description":"Bootstrapped & distributed backend-as-a-service with user-controlled data","contact":{"name":"Team Fission","url":"https://fission.codes","email":"support@fission.codes"},"license":{"name":"AGPL 3.0","url":"https://www.gnu.org/licenses/agpl-3.0.en.html"},"version":"2.16.0.0"},"servers":[{"url":"https://runfission.net/"}],"paths":{"/api/app/{appId}":{"delete":{"summary":"Destroy app by ID","description":"Destroy app by its ID","parameters":[{"name":"appId","in":"path","required":true,"schema":{"minimum":0,"exclusiveMinimum":false,"type":"integer"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`appId` not found","content":{}}}}},"/docs":{"get":{"summary":"Docs","description":"Swagger-based documentation","responses":{"200":{"description":"","content":{"text/html;charset=utf-8":{"schema":{"$ref":"#/components/schemas/HTML Docs"}}}}}}},"/api/user/data/{newCID}":{"put":{"summary":"Update data root","description":"Set/update currently authenticated user's file system content","parameters":[{"name":"newCID","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`newCID` not found","content":{}}}}},"/api/user/email/recover/{Username}":{"post":{"summary":"Email verification for account recovery","parameters":[{"name":"Username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`Username` not found","content":{}}}}},"/api/user/email/verify/{Challenge}":{"get":{"summary":"Email verification","parameters":[{"name":"Challenge","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`Challenge` not found","content":{}}}}},"/docs/index.html":{"get":{"summary":"Docs","description":"Swagger-based documentation","responses":{"200":{"description":"","content":{"text/html;charset=utf-8":{"schema":{"$ref":"#/components/schemas/HTML Docs"}}}}}}},"/api/user/email/resend":{"post":{"summary":"Resend verification email","description":"Send a verification email to currently authenticated user.","responses":{"204":{"description":"","content":{}}}}},"/api/auth/ucan":{"post":{"summary":"Verify a UCAN","description":"Check if a UCAN is validly formatted","parameters":[{"name":"ignore_time","in":"query","allowEmptyValue":true,"schema":{"type":"boolean","default":false}}],"requestBody":{"content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/BareUCAN"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `ignore_time` or `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/api/app/{App URL}/{New CID}":{"put":{"summary":"Set app content","description":"Update the content (CID) for an app","parameters":[{"name":"App URL","in":"path","required":true,"schema":{"type":"string"}},{"name":"New CID","in":"path","required":true,"schema":{"type":"string"}},{"name":"copy-data","in":"query","schema":{"type":"boolean"}}],"responses":{"202":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"maxItems":0,"type":"array","example":[],"items":{"type":"object"}}}}},"400":{"description":"Invalid `copy-data`","content":{}},"404":{"description":"`App URL` or `New CID` not found","content":{}}}}},"/api/user/data/{username}":{"get":{"summary":"Get Data Root","description":"Retrieve a user's data root from DNS","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}},"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}}}},"404":{"description":"`username` not found","content":{}}}}},"/api/app/associated/{url}":{"delete":{"summary":"Destroy app by URL","description":"Destroy app by any associated URL","parameters":[{"name":"url","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`url` not found","content":{}}}}},"/api/user/did":{"put":{"summary":"Update Public Key","description":"Set currently authenticated user's root public key to another one","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/PublicKey"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/docs.json":{"get":{"summary":"Docs","description":"Swagger-based documentation","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/JSON"}}}}}}},"/api/ipfs/peers":{"get":{"summary":"Peer index","description":"List of recommended IPFS peers","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}},"text/plain;charset=utf-8":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}},"application/octet-stream":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}}}}}}},"/api/user/did/{Username}/{Challenge}":{"put":{"summary":"Update Public Key via Email Challenge","description":"Set given username's public key to something else via providing a challenge obtained from /user/email/recover","parameters":[{"name":"Username","in":"path","required":true,"schema":{"type":"string"}},{"name":"Challenge","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/PublicKey"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}},"404":{"description":"`Username` or `Challenge` not found","content":{}}},"x-codegen-request-body-name":"body"}},"/api/user/whoami":{"get":{"summary":"Get username","description":"Get username registered to currently authenticated user","responses":{"200":{"description":"","content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Username"}},"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Username"}}}}}}},"/api/user":{"put":{"summary":"Create user with DID and UCAN proof","description":"Register a new user (must auth with user-controlled DID)","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Registration"}}},"required":true},"responses":{"201":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/api/app":{"get":{"summary":"App index","description":"A list of all of your apps and their associated domain names","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/App Index Payload"}}}}}}},"post":{"summary":"Create app","description":"Creates a new app, assigns an initial subdomain, and sets an asset placeholder","parameters":[{"name":"subdomain","in":"query","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/URL"}}}},"400":{"description":"Invalid `subdomain`","content":{}}}}}},"components":{"schemas":{"IPFSAddress":{"type":"string","example":"QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ"},"BareUCAN":{"type":"string","description":"An encoded UCAN (JWT) *without* a 'bearer' header tag","example":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVhdiI6IjAuMS4wIn0.eyJhdWQiOiJkaWQ6a2V5OnpTdEVacHpTTXRUdDlrMnZzemd2Q3dGNGZMUVFTeUExNVc1QVE0ejNBUjZCeDRlRko1Y3JKRmJ1R3hLbWJtYTQiLCJleHAiOjE1OTE2Mjc4NDEsImlzcyI6ImRpZDprZXk6ejEzVjNTb2cyWWFVS2hkR0NtZ3g5VVp1VzFvMVNoRkpZYzZEdkdZZTdOVHQ2ODlOb0wzazdIdXdCUXhKZFBqdllURHhFd3kxbTh3YjZwOTRjNm1NWTRmTnFBV0RkeVk3NVNWMnFEODVLNU1ZcVpqYUpZOGM0NzFBUEZydkpTZEo1QXo1REVDaENnV0xOdkVYRjJxaFlSMkZWaVprVGhvRVB0Mk5ZcHVxZ0txZVZvS1RpZkRpd3JYeUhka3hCazJNOWNQZE5HaGczRE0xWTZyVGY2RDJIZ2JlUnF2OGtvVW9xeWlLTWpYYUZTZlFZVkY3cGZGWGhOYWdKRGZqcG9xQ3FWWFllaTFQbU43UzM0cFdvcTZwUmRQczY5N2F4VVRFNXZQeXNlU3ROc3o4SGFqdUp2NzlDSENNZ2RvRkJzOXc3UHZNSFVEeGdHUWR0c3hBQXZKRzRxVGJkU0I2bUd2TFp0cGE5czFNemNIcDVEV1NjaUJxNnF1aG1SSHRTVFdHNW9FSnRTdlN4QlhTczJoZFBId0I0QVUiLCJuYmYiOjE1OTE2Mjc3NTEsInByZiI6ImV5SmhiR2NpT2lKU1V6STFOaUlzSW5SNWNDSTZJa3BYVkNJc0luVmhkaUk2SWpBdU1TNHdJbjAuZXlKaGRXUWlPaUprYVdRNmEyVjVPbm94TTFZelUyOW5NbGxoVlV0b1pFZERiV2Q0T1ZWYWRWY3hiekZUYUVaS1dXTTJSSFpIV1dVM1RsUjBOamc1VG05TU0yczNTSFYzUWxGNFNtUlFhblpaVkVSNFJYZDVNVzA0ZDJJMmNEazBZelp0VFZrMFprNXhRVmRFWkhsWk56VlRWakp4UkRnMVN6Vk5XWEZhYW1GS1dUaGpORGN4UVZCR2NuWktVMlJLTlVGNk5VUkZRMmhEWjFkTVRuWkZXRVl5Y1doWlVqSkdWbWxhYTFSb2IwVlFkREpPV1hCMWNXZExjV1ZXYjB0VWFXWkVhWGR5V0hsSVpHdDRRbXN5VFRsalVHUk9SMmhuTTBSTk1WazJjbFJtTmtReVNHZGlaVkp4ZGpocmIxVnZjWGxwUzAxcVdHRkdVMlpSV1ZaR04zQm1SbGhvVG1GblNrUm1hbkJ2Y1VOeFZsaFpaV2t4VUcxT04xTXpOSEJYYjNFMmNGSmtVSE0yT1RkaGVGVlVSVFYyVUhselpWTjBUbk42T0VoaGFuVktkamM1UTBoRFRXZGtiMFpDY3psM04xQjJUVWhWUkhoblIxRmtkSE40UVVGMlNrYzBjVlJpWkZOQ05tMUhka3hhZEhCaE9YTXhUWHBqU0hBMVJGZFRZMmxDY1RaeGRXaHRVa2gwVTFSWFJ6VnZSVXAwVTNaVGVFSllVM015YUdSUVNIZENORUZWSWl3aVpYaHdJam94TlRrME1qRTVOelE0TENKcGMzTWlPaUprYVdRNmEyVjVPbm94TTFZelUyOW5NbGxoVlV0b1pFZERiV2Q0T1ZWYWRWY3hiekZUYUVaS1dXTTJSSFpIV1dVM1RsUjBOamc1VG05TU0wWjFRVlIwVlZCV1p6ZHBXRGQ0YlUxdGNrbzJNVE0wVkcxaE1tSkdWWE5YVVhreVRtUkhTREZYYVRSSWVVNWhOemh3VG0xU1RrRkdVRWhHU21KcVNqRnhZemc0TkZoeE1XbHlhV2wwY1ZKVk0zQmtkRVJSVFhobmIyRjNNVUptVFZkRlRVWnJkVmxWUm5Gd1JFdGlSMHd6WTNKQ2VtNUxkbFpNZDJsRGExQkhiM2h0V0VGWE4waFZOemw2TmxCVVRVZDVVMHRDUlVGMVdERjNSVE0wTlRKQ05rbzVOblphZFc5aVJUTlpZVUV5T0hsTFMwaE1OV2xxWmtKVVJFVTFaRTF6TmpWaFJraGlSbVZUZDNONlJtMWxkVkZxTkdkS1JEVklaMUJOYjI1bGRHZzNUSFZIWlhVMFlWVldWMFZDVkZKdk5sWmlTbFpRTVdKSVNqZHhUbUZRWW1JMFNrUjRTa2hFUkhaeFV6Vm9PRlJCZFZVMmIweFNUa1ZuTTJSdU4xSnBjV295VW1ST1ZYbFRkbkZxVkU0MWQzUk1VMjl3ZGtSNlFVSXllbFl5VUhSYWNETjJNVEZPYjJaRWEyNTJSWFpYYTBONmRYbFdRVnA1VFVGbk9HZGFXa2RESWl3aWJtSm1Jam94TlRreE5qSTNOamc0TENKd2RHTWlPaUpCVUZCRlRrUWlMQ0p6WTNBaU9pSXZJbjAuZWFIcmZuaFJkdy1ob1B3Q2RjVXpTX09abm5VXzFIR3RwU0JHenM1SmtDcGs5RlVQZVYwU2xVbF9kUkI0UzZ0M2xnbi14UHVoaVA3WE5kMGM3Qm9hZFd0SkxMSlY4VV9MZ2pUUUdMa1h4al9yVTZrYXA4bFRibllneDZPZzFiZi10bUhlVVVCNFZOY2RFUGlTMFRUYllMZlFDN05rLTZzbWkwekNYQlVBd1JrLURSQURtdkdhMzloVzFMQlFqWl9oejVhOVRYTTlRb0drS0szQkxDM2JVbXFKU1Y0SjVCTmlxanQ0TktqOUo1RjVYYjdHNTd4MkttWkVMYUw1U2NYV1lvWmpxVlJNWF9MY3k1WE4xaUJvWmFHVHlFbzlVNVBNYzhRSVRoaEdQTXNtc2JTS1cxc1AyUFF6OGNOUHh5b2NXYmZsT0dQZkVGZ21aenk4RGwxTkN3IiwicHRjIjoiQVBQRU5EIiwic2NwIjoiLyJ9"},"JSON":{"type":"integer"},"URL":{"type":"string","description":"A domain name, potentially with a subdomain","example":"foo.example.com"},"PublicKey":{"type":"string","description":"A public key"},"IPFSPeer":{"type":"string","description":"An IPFS peer address","example":"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd"},"HTML Docs":{"type":"integer"},"Username":{"type":"string","example":"username"},"UTCTime":{"type":"string","format":"yyyy-mm-ddThh:MM:ssZ","example":"2016-07-22T00:00:00Z"},"App Index Payload":{"required":["insertedAt","modifiedAt","urls"],"type":"object","properties":{"modifiedAt":{"$ref":"#/components/schemas/UTCTime"},"urls":{"type":"array","items":{"$ref":"#/components/schemas/URL"}},"insertedAt":{"$ref":"#/components/schemas/UTCTime"}},"description":"Properties for a registered application","example":{"modifiedAt":"2021-05-10T01:26:40Z","urls":["my-cool-subdomain.fission.codes"],"insertedAt":"2021-05-09T22:40:00Z"}},"Registration":{"required":["email","username"],"type":"object","properties":{"email":{"type":"string"},"username":{"type":"string"}},"description":"The information that a user needs to provide to login/register.","example":{"email":"alice@example.com","username":"username"}}},"securitySchemes":{"User-originated DID Registration":{"type":"apiKey","description":"A higher-order auth type that accepts both Basic Auth and Fission-formatted JWTs as described here: https://whitepaper.fission.codes/identity/authentication","name":"Authorization","in":"header"},"Fission Auth":{"type":"apiKey","description":"A higher-order auth type that accepts both Basic Auth and Fission-formatted JWTs as described here: https://whitepaper.fission.codes/identity/authentication","name":"Authorization","in":"header"}}}} \ No newline at end of file diff --git a/swagger_snapshots/fission-web-api-2.0.1.0/v_.json b/swagger_snapshots/fission-web-api-2.0.1.0/v_.json new file mode 100644 index 000000000..9ac19305a --- /dev/null +++ b/swagger_snapshots/fission-web-api-2.0.1.0/v_.json @@ -0,0 +1 @@ +{"openapi":"3.0.1","info":{"title":"The Fission API","description":"Bootstrapped & distributed backend-as-a-service with user-controlled data","contact":{"name":"Team Fission","url":"https://fission.codes","email":"support@fission.codes"},"license":{"name":"AGPL 3.0","url":"https://www.gnu.org/licenses/agpl-3.0.en.html"},"version":"2.16.0.0"},"servers":[{"url":"https://runfission.net/"}],"paths":{"/api/app/{appId}":{"delete":{"summary":"Destroy app by ID","description":"Destroy app by its ID","parameters":[{"name":"appId","in":"path","required":true,"schema":{"minimum":0,"exclusiveMinimum":false,"type":"integer"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`appId` not found","content":{}}}}},"/docs":{"get":{"summary":"Docs","description":"Swagger-based documentation","responses":{"200":{"description":"","content":{"text/html;charset=utf-8":{"schema":{"$ref":"#/components/schemas/HTML Docs"}}}}}}},"/api/user/data/{newCID}":{"put":{"summary":"Update data root","description":"Set/update currently authenticated user's file system content","parameters":[{"name":"newCID","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`newCID` not found","content":{}}}}},"/api/user/email/recover/{Username}":{"post":{"summary":"Email verification for account recovery","parameters":[{"name":"Username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`Username` not found","content":{}}}}},"/api/user/email/verify/{Challenge}":{"get":{"summary":"Email verification","parameters":[{"name":"Challenge","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`Challenge` not found","content":{}}}}},"/docs/index.html":{"get":{"summary":"Docs","description":"Swagger-based documentation","responses":{"200":{"description":"","content":{"text/html;charset=utf-8":{"schema":{"$ref":"#/components/schemas/HTML Docs"}}}}}}},"/api/user/email/resend":{"post":{"summary":"Resend verification email","description":"Send a verification email to currently authenticated user.","responses":{"204":{"description":"","content":{}}}}},"/api/auth/ucan":{"post":{"summary":"Verify a UCAN","description":"Check if a UCAN is validly formatted","parameters":[{"name":"ignore_time","in":"query","allowEmptyValue":true,"schema":{"type":"boolean","default":false}}],"requestBody":{"content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/BareUCAN"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `ignore_time` or `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/api/app/{App URL}/{New CID}":{"put":{"summary":"Set app content","description":"Update the content (CID) for an app","parameters":[{"name":"App URL","in":"path","required":true,"schema":{"type":"string"}},{"name":"New CID","in":"path","required":true,"schema":{"type":"string"}},{"name":"copy-data","in":"query","schema":{"type":"boolean"}}],"responses":{"202":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"maxItems":0,"type":"array","example":[],"items":{"type":"object"}}}}},"400":{"description":"Invalid `copy-data`","content":{}},"404":{"description":"`App URL` or `New CID` not found","content":{}}}}},"/api/user/data/{username}":{"get":{"summary":"Get Data Root","description":"Retrieve a user's data root from DNS","parameters":[{"name":"username","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}},"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/IPFSAddress"}}}},"404":{"description":"`username` not found","content":{}}}}},"/api/app/associated/{url}":{"delete":{"summary":"Destroy app by URL","description":"Destroy app by any associated URL","parameters":[{"name":"url","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"","content":{}},"404":{"description":"`url` not found","content":{}}}}},"/api/user/did":{"put":{"summary":"Update Public Key","description":"Set currently authenticated user's root public key to another one","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/PublicKey"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/docs.json":{"get":{"summary":"Docs","description":"Swagger-based documentation","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/JSON"}}}}}}},"/api/ipfs/peers":{"get":{"summary":"Peer index","description":"List of recommended IPFS peers","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}},"text/plain;charset=utf-8":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}},"application/octet-stream":{"schema":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/IPFSPeer"}}}}}}}},"/api/user/did/{Username}/{Challenge}":{"put":{"summary":"Update Public Key via Email Challenge","description":"Set given username's public key to something else via providing a challenge obtained from /user/email/recover","parameters":[{"name":"Username","in":"path","required":true,"schema":{"type":"string"}},{"name":"Challenge","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/PublicKey"}}},"required":true},"responses":{"204":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}},"404":{"description":"`Username` or `Challenge` not found","content":{}}},"x-codegen-request-body-name":"body"}},"/api/user/whoami":{"get":{"summary":"Get username","description":"Get username registered to currently authenticated user","responses":{"200":{"description":"","content":{"text/plain;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Username"}},"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Username"}}}}}}},"/api/user":{"put":{"summary":"Create user with DID and UCAN proof","description":"Register a new user (must auth with user-controlled DID)","requestBody":{"content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/Registration"}}},"required":true},"responses":{"201":{"description":"","content":{}},"400":{"description":"Invalid `body`","content":{}}},"x-codegen-request-body-name":"body"}},"/api/app":{"get":{"summary":"App index","description":"A list of all of your apps and their associated domain names","responses":{"200":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/App Index Payload"}}}}}}},"post":{"summary":"Create app","description":"Creates a new app, assigns an initial subdomain, and sets an asset placeholder","parameters":[{"name":"subdomain","in":"query","schema":{"type":"string"}}],"responses":{"202":{"description":"","content":{"application/json;charset=utf-8":{"schema":{"$ref":"#/components/schemas/URL"}}}},"400":{"description":"Invalid `subdomain`","content":{}}}}}},"components":{"schemas":{"IPFSAddress":{"type":"string","example":"QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ"},"BareUCAN":{"type":"string","description":"An encoded UCAN (JWT) *without* a 'bearer' header tag","example":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsInVhdiI6IjAuMS4wIn0.eyJhdWQiOiJkaWQ6a2V5OnpTdEVacHpTTXRUdDlrMnZzemd2Q3dGNGZMUVFTeUExNVc1QVE0ejNBUjZCeDRlRko1Y3JKRmJ1R3hLbWJtYTQiLCJleHAiOjE1OTE2Mjc4NDEsImlzcyI6ImRpZDprZXk6ejEzVjNTb2cyWWFVS2hkR0NtZ3g5VVp1VzFvMVNoRkpZYzZEdkdZZTdOVHQ2ODlOb0wzazdIdXdCUXhKZFBqdllURHhFd3kxbTh3YjZwOTRjNm1NWTRmTnFBV0RkeVk3NVNWMnFEODVLNU1ZcVpqYUpZOGM0NzFBUEZydkpTZEo1QXo1REVDaENnV0xOdkVYRjJxaFlSMkZWaVprVGhvRVB0Mk5ZcHVxZ0txZVZvS1RpZkRpd3JYeUhka3hCazJNOWNQZE5HaGczRE0xWTZyVGY2RDJIZ2JlUnF2OGtvVW9xeWlLTWpYYUZTZlFZVkY3cGZGWGhOYWdKRGZqcG9xQ3FWWFllaTFQbU43UzM0cFdvcTZwUmRQczY5N2F4VVRFNXZQeXNlU3ROc3o4SGFqdUp2NzlDSENNZ2RvRkJzOXc3UHZNSFVEeGdHUWR0c3hBQXZKRzRxVGJkU0I2bUd2TFp0cGE5czFNemNIcDVEV1NjaUJxNnF1aG1SSHRTVFdHNW9FSnRTdlN4QlhTczJoZFBId0I0QVUiLCJuYmYiOjE1OTE2Mjc3NTEsInByZiI6ImV5SmhiR2NpT2lKU1V6STFOaUlzSW5SNWNDSTZJa3BYVkNJc0luVmhkaUk2SWpBdU1TNHdJbjAuZXlKaGRXUWlPaUprYVdRNmEyVjVPbm94TTFZelUyOW5NbGxoVlV0b1pFZERiV2Q0T1ZWYWRWY3hiekZUYUVaS1dXTTJSSFpIV1dVM1RsUjBOamc1VG05TU0yczNTSFYzUWxGNFNtUlFhblpaVkVSNFJYZDVNVzA0ZDJJMmNEazBZelp0VFZrMFprNXhRVmRFWkhsWk56VlRWakp4UkRnMVN6Vk5XWEZhYW1GS1dUaGpORGN4UVZCR2NuWktVMlJLTlVGNk5VUkZRMmhEWjFkTVRuWkZXRVl5Y1doWlVqSkdWbWxhYTFSb2IwVlFkREpPV1hCMWNXZExjV1ZXYjB0VWFXWkVhWGR5V0hsSVpHdDRRbXN5VFRsalVHUk9SMmhuTTBSTk1WazJjbFJtTmtReVNHZGlaVkp4ZGpocmIxVnZjWGxwUzAxcVdHRkdVMlpSV1ZaR04zQm1SbGhvVG1GblNrUm1hbkJ2Y1VOeFZsaFpaV2t4VUcxT04xTXpOSEJYYjNFMmNGSmtVSE0yT1RkaGVGVlVSVFYyVUhselpWTjBUbk42T0VoaGFuVktkamM1UTBoRFRXZGtiMFpDY3psM04xQjJUVWhWUkhoblIxRmtkSE40UVVGMlNrYzBjVlJpWkZOQ05tMUhka3hhZEhCaE9YTXhUWHBqU0hBMVJGZFRZMmxDY1RaeGRXaHRVa2gwVTFSWFJ6VnZSVXAwVTNaVGVFSllVM015YUdSUVNIZENORUZWSWl3aVpYaHdJam94TlRrME1qRTVOelE0TENKcGMzTWlPaUprYVdRNmEyVjVPbm94TTFZelUyOW5NbGxoVlV0b1pFZERiV2Q0T1ZWYWRWY3hiekZUYUVaS1dXTTJSSFpIV1dVM1RsUjBOamc1VG05TU0wWjFRVlIwVlZCV1p6ZHBXRGQ0YlUxdGNrbzJNVE0wVkcxaE1tSkdWWE5YVVhreVRtUkhTREZYYVRSSWVVNWhOemh3VG0xU1RrRkdVRWhHU21KcVNqRnhZemc0TkZoeE1XbHlhV2wwY1ZKVk0zQmtkRVJSVFhobmIyRjNNVUptVFZkRlRVWnJkVmxWUm5Gd1JFdGlSMHd6WTNKQ2VtNUxkbFpNZDJsRGExQkhiM2h0V0VGWE4waFZOemw2TmxCVVRVZDVVMHRDUlVGMVdERjNSVE0wTlRKQ05rbzVOblphZFc5aVJUTlpZVUV5T0hsTFMwaE1OV2xxWmtKVVJFVTFaRTF6TmpWaFJraGlSbVZUZDNONlJtMWxkVkZxTkdkS1JEVklaMUJOYjI1bGRHZzNUSFZIWlhVMFlWVldWMFZDVkZKdk5sWmlTbFpRTVdKSVNqZHhUbUZRWW1JMFNrUjRTa2hFUkhaeFV6Vm9PRlJCZFZVMmIweFNUa1ZuTTJSdU4xSnBjV295VW1ST1ZYbFRkbkZxVkU0MWQzUk1VMjl3ZGtSNlFVSXllbFl5VUhSYWNETjJNVEZPYjJaRWEyNTJSWFpYYTBONmRYbFdRVnA1VFVGbk9HZGFXa2RESWl3aWJtSm1Jam94TlRreE5qSTNOamc0TENKd2RHTWlPaUpCVUZCRlRrUWlMQ0p6WTNBaU9pSXZJbjAuZWFIcmZuaFJkdy1ob1B3Q2RjVXpTX09abm5VXzFIR3RwU0JHenM1SmtDcGs5RlVQZVYwU2xVbF9kUkI0UzZ0M2xnbi14UHVoaVA3WE5kMGM3Qm9hZFd0SkxMSlY4VV9MZ2pUUUdMa1h4al9yVTZrYXA4bFRibllneDZPZzFiZi10bUhlVVVCNFZOY2RFUGlTMFRUYllMZlFDN05rLTZzbWkwekNYQlVBd1JrLURSQURtdkdhMzloVzFMQlFqWl9oejVhOVRYTTlRb0drS0szQkxDM2JVbXFKU1Y0SjVCTmlxanQ0TktqOUo1RjVYYjdHNTd4MkttWkVMYUw1U2NYV1lvWmpxVlJNWF9MY3k1WE4xaUJvWmFHVHlFbzlVNVBNYzhRSVRoaEdQTXNtc2JTS1cxc1AyUFF6OGNOUHh5b2NXYmZsT0dQZkVGZ21aenk4RGwxTkN3IiwicHRjIjoiQVBQRU5EIiwic2NwIjoiLyJ9"},"JSON":{"type":"integer"},"URL":{"type":"string","description":"A domain name, potentially with a subdomain","example":"foo.example.com"},"PublicKey":{"type":"string","description":"A public key"},"IPFSPeer":{"type":"string","description":"An IPFS peer address","example":"/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd"},"HTML Docs":{"type":"integer"},"Username":{"type":"string","example":"username"},"UTCTime":{"type":"string","format":"yyyy-mm-ddThh:MM:ssZ","example":"2016-07-22T00:00:00Z"},"App Index Payload":{"required":["insertedAt","modifiedAt","urls"],"type":"object","properties":{"modifiedAt":{"$ref":"#/components/schemas/UTCTime"},"urls":{"type":"array","items":{"$ref":"#/components/schemas/URL"}},"insertedAt":{"$ref":"#/components/schemas/UTCTime"}},"description":"Properties for a registered application","example":{"modifiedAt":"2021-05-10T01:26:40Z","urls":["my-cool-subdomain.fission.codes"],"insertedAt":"2021-05-09T22:40:00Z"}},"Registration":{"required":["email","username"],"type":"object","properties":{"email":{"type":"string"},"username":{"type":"string"}},"description":"The information that a user needs to provide to login/register.","example":{"email":"alice@example.com","username":"username"}}},"securitySchemes":{"User-originated DID Registration":{"type":"apiKey","description":"A higher-order auth type that accepts both Basic Auth and Fission-formatted JWTs as described here: https://whitepaper.fission.codes/identity/authentication","name":"Authorization","in":"header"},"Fission Auth":{"type":"apiKey","description":"A higher-order auth type that accepts both Basic Auth and Fission-formatted JWTs as described here: https://whitepaper.fission.codes/identity/authentication","name":"Authorization","in":"header"}}}} \ No newline at end of file diff --git a/tools.nix b/tools.nix new file mode 100644 index 000000000..20b263d88 --- /dev/null +++ b/tools.nix @@ -0,0 +1,27 @@ +{ rosetta ? false }: + let + overrides = if rosetta then { system = "x86_64-darwin"; } else {}; + + sources = import ./nix/sources.nix; + nixos = import sources.nixos overrides; + darwin = import sources.darwin overrides; + unstable = import sources.unstable overrides; + + pkgs = if darwin.stdenv.isDarwin then darwin else nixos; + loadtest = if pkgs.stdenv.isLinux then [pkgs.wrk2] else []; + + in + pkgs.mkShell { + nativeBuildInputs = [ + pkgs.nodejs + pkgs.yarn + ] ++ loadtest; + + shellHook = '' + export LANG=C.UTF8 + + echo " Setting up openapi-diff" + yarn add openapi-diff + alias openapi-diff="./node_modules/openapi-diff/bin/openapi-diff" + ''; + }