Skip to content

Instantly share code, notes, and snippets.

@marcelbeumer
Created October 21, 2021 11:17
Show Gist options
  • Save marcelbeumer/e1d39a132d64bd870942a71c26f88726 to your computer and use it in GitHub Desktop.
Save marcelbeumer/e1d39a132d64bd870942a71c26f88726 to your computer and use it in GitHub Desktop.
lsp.log for codenav issue with nvim
[START][2021-10-21 13:16:21] LSP logging initiated
[INFO][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:258 "Starting RPC client" {
args = { "lsp" },
cmd = "deno",
extra = {}
}
[TRACE][2021-10-21 13:16:26] .../lua/vim/lsp.lua:843 "LSP[denols]" "initialize_params" {
capabilities = {
callHierarchy = {
dynamicRegistration = false
},
textDocument = {
codeAction = {
codeActionLiteralSupport = {
codeActionKind = {
valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" }
}
},
dataSupport = true,
dynamicRegistration = false,
resolveSupport = {
properties = { "edit" }
}
},
completion = {
completionItem = {
commitCharactersSupport = false,
deprecatedSupport = false,
documentationFormat = { "markdown", "plaintext" },
preselectSupport = false,
snippetSupport = false
},
completionItemKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }
},
contextSupport = false,
dynamicRegistration = false
},
declaration = {
linkSupport = true
},
definition = {
linkSupport = true
},
documentHighlight = {
dynamicRegistration = false
},
documentSymbol = {
dynamicRegistration = false,
hierarchicalDocumentSymbolSupport = true,
symbolKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }
}
},
hover = {
contentFormat = { "markdown", "plaintext" },
dynamicRegistration = false
},
implementation = {
linkSupport = true
},
publishDiagnostics = {
relatedInformation = true,
tagSupport = {
valueSet = { 1, 2 }
}
},
references = {
dynamicRegistration = false
},
rename = {
dynamicRegistration = false,
prepareSupport = true
},
signatureHelp = {
dynamicRegistration = false,
signatureInformation = {
activeParameterSupport = true,
documentationFormat = { "markdown", "plaintext" },
parameterInformation = {
labelOffsetSupport = true
}
}
},
synchronization = {
didSave = true,
dynamicRegistration = false,
willSave = false,
willSaveWaitUntil = false
},
typeDefinition = {
linkSupport = true
}
},
window = {
showDocument = {
support = false
},
showMessage = {
messageActionItem = {
additionalPropertiesSupport = false
}
},
workDoneProgress = true
},
workspace = {
applyEdit = true,
configuration = true,
symbol = {
dynamicRegistration = false,
hierarchicalWorkspaceSymbolSupport = true,
symbolKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }
}
},
workspaceEdit = {
resourceOperations = { "rename", "create", "delete" }
},
workspaceFolders = true
}
},
clientInfo = {
name = "Neovim",
version = "0.6.0"
},
initializationOptions = {
enable = true,
lint = false,
unstable = false
},
processId = 25029,
rootPath = "/Users/robotx/dev/tmp/deno_oak_test",
rootUri = "file:///Users/robotx/dev/tmp/deno_oak_test",
trace = "off",
workspaceFolders = { {
name = "/Users/robotx/dev/tmp/deno_oak_test",
uri = "file:///Users/robotx/dev/tmp/deno_oak_test"
} }
}
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:337 "rpc.send" {
id = 1,
jsonrpc = "2.0",
method = "initialize",
params = {
capabilities = {
callHierarchy = {
dynamicRegistration = false
},
textDocument = {
codeAction = {
codeActionLiteralSupport = {
codeActionKind = {
valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" }
}
},
dataSupport = true,
dynamicRegistration = false,
resolveSupport = {
properties = { "edit" }
}
},
completion = {
completionItem = {
commitCharactersSupport = false,
deprecatedSupport = false,
documentationFormat = { "markdown", "plaintext" },
preselectSupport = false,
snippetSupport = false
},
completionItemKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }
},
contextSupport = false,
dynamicRegistration = false
},
declaration = {
linkSupport = true
},
definition = {
linkSupport = true
},
documentHighlight = {
dynamicRegistration = false
},
documentSymbol = {
dynamicRegistration = false,
hierarchicalDocumentSymbolSupport = true,
symbolKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }
}
},
hover = {
contentFormat = { "markdown", "plaintext" },
dynamicRegistration = false
},
implementation = {
linkSupport = true
},
publishDiagnostics = {
relatedInformation = true,
tagSupport = {
valueSet = { 1, 2 }
}
},
references = {
dynamicRegistration = false
},
rename = {
dynamicRegistration = false,
prepareSupport = true
},
signatureHelp = {
dynamicRegistration = false,
signatureInformation = {
activeParameterSupport = true,
documentationFormat = { "markdown", "plaintext" },
parameterInformation = {
labelOffsetSupport = true
}
}
},
synchronization = {
didSave = true,
dynamicRegistration = false,
willSave = false,
willSaveWaitUntil = false
},
typeDefinition = {
linkSupport = true
}
},
window = {
showDocument = {
support = false
},
showMessage = {
messageActionItem = {
additionalPropertiesSupport = false
}
},
workDoneProgress = true
},
workspace = {
applyEdit = true,
configuration = true,
symbol = {
dynamicRegistration = false,
hierarchicalWorkspaceSymbolSupport = true,
symbolKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }
}
},
workspaceEdit = {
resourceOperations = { "rename", "create", "delete" }
},
workspaceFolders = true
}
},
clientInfo = {
name = "Neovim",
version = "0.6.0"
},
initializationOptions = {
enable = true,
lint = false,
unstable = false
},
processId = 25029,
rootPath = "/Users/robotx/dev/tmp/deno_oak_test",
rootUri = "file:///Users/robotx/dev/tmp/deno_oak_test",
trace = "off",
workspaceFolders = { {
name = "/Users/robotx/dev/tmp/deno_oak_test",
uri = "file:///Users/robotx/dev/tmp/deno_oak_test"
} }
}
}
[ERROR][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" "Starting Deno language server...\n"
[ERROR][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" ' version: 1.14.3 (release, x86_64-apple-darwin)\n executable: /Users/robotx/.asdf/installs/deno/1.14.3/bin/deno\nConnected to "Neovim" 0.6.0\n'
[ERROR][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" "language server initialized\n"
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:435 "rpc.receive" {
id = 1,
jsonrpc = "2.0",
result = {
capabilities = {
callHierarchyProvider = true,
codeActionProvider = {
codeActionKinds = { "quickfix", "refactor", "refactor.extract.function", "refactor.extract.constant", "refactor.extract.type", "refactor.extract.interface", "refactor.move.newFile", "refactor.rewrite.import", "refactor.rewrite.export", "refactor.rewrite.arrow.braces", "refactor.rewrite.parameters.toDestructured", "refactor.rewrite.property.generateAccessors" },
resolveProvider = true
},
codeLensProvider = {
resolveProvider = true
},
completionProvider = {
allCommitCharacters = { ".", ",", ";", "(" },
resolveProvider = true,
triggerCharacters = { ".", '"', "'", "`", "/", "@", "<", "#" }
},
definitionProvider = true,
documentFormattingProvider = true,
documentHighlightProvider = true,
documentSymbolProvider = true,
foldingRangeProvider = true,
hoverProvider = true,
implementationProvider = true,
referencesProvider = true,
renameProvider = true,
selectionRangeProvider = true,
semanticTokensProvider = {
full = true,
legend = {
tokenModifiers = { "declaration", "static", "async", "readonly", "defaultLibrary", "local" },
tokenTypes = { "class", "enum", "interface", "namespace", "typeParameter", "type", "parameter", "variable", "enumMember", "property", "function", "method" }
},
range = true
},
signatureHelpProvider = {
retriggerCharacters = { ")" },
triggerCharacters = { ",", "(", "<" }
},
textDocumentSync = {
change = 2,
openClose = true,
save = vim.empty_dict()
},
workspace = {
workspaceFolders = {
supported = true
}
}
},
serverInfo = {
name = "deno-language-server",
version = "1.14.3 (release, x86_64-apple-darwin)"
}
}
}
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:337 "rpc.send" {
jsonrpc = "2.0",
method = "initialized",
params = vim.empty_dict()
}
[DEBUG][2021-10-21 13:16:26] .../lua/vim/lsp.lua:870 "LSP[denols]" "server_capabilities" {
callHierarchyProvider = true,
codeActionProvider = {
codeActionKinds = { "quickfix", "refactor", "refactor.extract.function", "refactor.extract.constant", "refactor.extract.type", "refactor.extract.interface", "refactor.move.newFile", "refactor.rewrite.import", "refactor.rewrite.export", "refactor.rewrite.arrow.braces", "refactor.rewrite.parameters.toDestructured", "refactor.rewrite.property.generateAccessors" },
resolveProvider = true
},
codeLensProvider = {
resolveProvider = true
},
completionProvider = {
allCommitCharacters = { ".", ",", ";", "(" },
resolveProvider = true,
triggerCharacters = { ".", '"', "'", "`", "/", "@", "<", "#" }
},
definitionProvider = true,
documentFormattingProvider = true,
documentHighlightProvider = true,
documentSymbolProvider = true,
foldingRangeProvider = true,
hoverProvider = true,
implementationProvider = true,
referencesProvider = true,
renameProvider = true,
selectionRangeProvider = true,
semanticTokensProvider = {
full = true,
legend = {
tokenModifiers = { "declaration", "static", "async", "readonly", "defaultLibrary", "local" },
tokenTypes = { "class", "enum", "interface", "namespace", "typeParameter", "type", "parameter", "variable", "enumMember", "property", "function", "method" }
},
range = true
},
signatureHelpProvider = {
retriggerCharacters = { ")" },
triggerCharacters = { ",", "(", "<" }
},
textDocumentSync = {
change = 2,
openClose = true,
save = vim.empty_dict()
},
workspace = {
workspaceFolders = {
supported = true
}
}
}
[INFO][2021-10-21 13:16:26] .../lua/vim/lsp.lua:871 "LSP[denols]" "initialized" {
resolved_capabilities = {
call_hierarchy = true,
code_action = {
codeActionKinds = { "quickfix", "refactor", "refactor.extract.function", "refactor.extract.constant", "refactor.extract.type", "refactor.extract.interface", "refactor.move.newFile", "refactor.rewrite.import", "refactor.rewrite.export", "refactor.rewrite.arrow.braces", "refactor.rewrite.parameters.toDestructured", "refactor.rewrite.property.generateAccessors" },
resolveProvider = true
},
code_lens = true,
code_lens_resolve = true,
completion = true,
declaration = false,
document_formatting = true,
document_highlight = true,
document_range_formatting = false,
document_symbol = true,
execute_command = false,
find_references = true,
goto_definition = true,
hover = true,
implementation = true,
rename = true,
signature_help = true,
signature_help_trigger_characters = { ",", "(", "<" },
text_document_did_change = 2,
text_document_open_close = true,
text_document_save = vim.empty_dict(),
text_document_save_include_text = false,
text_document_will_save = false,
text_document_will_save_wait_until = false,
type_definition = false,
workspace_folder_properties = {
changeNotifications = false,
supported = true
},
workspace_symbol = false
}
}
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:337 "rpc.send" {
jsonrpc = "2.0",
method = "textDocument/didOpen",
params = {
textDocument = {
languageId = "typescript",
text = 'import {\n Application,\n Context,\n Middleware,\n} from "https://deno.land/x/[email protected]/mod.ts";\n\ninterface MyState {\n userId?: number;\n}\n\nconst app = new Application();\n\nconst userIdMiddleware: Middleware<MyState, Context<MyState, {}>> = async (\n ctx,\n next,\n) => {\n const userId = 1000;\n ctx.state.userId = userId;\n await next();\n};\n\napp.use(userIdMiddleware).use(async (ctx, next) => {\n ctx.state.userId;\n ctx.response.body = "Hello world!";\n await next();\n});\n\nawait app.listen("127.0.0.1:8000");\n',
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
version = 0
}
}
}
[ERROR][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" "Server ready.\n"
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:435 "rpc.receive" {
id = 0,
jsonrpc = "2.0",
method = "workspace/configuration",
params = {
items = { {
scopeUri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
section = "deno"
} }
}
}
[TRACE][2021-10-21 13:16:26] .../lua/vim/lsp.lua:705 "server_request" "workspace/configuration" {
items = { {
scopeUri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
section = "deno"
} }
}
[TRACE][2021-10-21 13:16:26] .../lua/vim/lsp.lua:708 "server_request: found handler for" "workspace/configuration"
[TRACE][2021-10-21 13:16:26] ...lsp/handlers.lua:432 "default_handler" "workspace/configuration" {
ctx = '{\n client_id = 1,\n method = "workspace/configuration"\n}',
result = {
items = { {
scopeUri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
section = "deno"
} }
}
}
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:445 "server_request: callback result" {
result = { vim.NIL },
status = true
}
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:337 "rpc.send" {
id = 0,
jsonrpc = "2.0",
result = { vim.NIL }
}
[ERROR][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" "Error converting specifier settings: invalid type: null, expected struct SpecifierSettings\n"
[DEBUG][2021-10-21 13:16:26] .../vim/lsp/rpc.lua:435 "rpc.receive" {
jsonrpc = "2.0",
method = "textDocument/publishDiagnostics",
params = {
diagnostics = {},
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
version = 0
}
}
[TRACE][2021-10-21 13:16:26] .../lua/vim/lsp.lua:691 "notification" "textDocument/publishDiagnostics" {
diagnostics = {},
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
version = 0
}
[TRACE][2021-10-21 13:16:26] ...lsp/handlers.lua:432 "default_handler" "textDocument/publishDiagnostics" {
ctx = '{\n client_id = 1,\n method = "textDocument/publishDiagnostics"\n}',
result = {
diagnostics = {},
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
version = 0
}
}
[DEBUG][2021-10-21 13:16:27] .../vim/lsp/rpc.lua:435 "rpc.receive" {
jsonrpc = "2.0",
method = "textDocument/publishDiagnostics",
params = {
diagnostics = {},
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
version = 0
}
}
[TRACE][2021-10-21 13:16:27] .../lua/vim/lsp.lua:691 "notification" "textDocument/publishDiagnostics" {
diagnostics = {},
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
version = 0
}
[TRACE][2021-10-21 13:16:27] ...lsp/handlers.lua:432 "default_handler" "textDocument/publishDiagnostics" {
ctx = '{\n client_id = 1,\n method = "textDocument/publishDiagnostics"\n}',
result = {
diagnostics = {},
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts",
version = 0
}
}
[DEBUG][2021-10-21 13:16:31] .../lua/vim/lsp.lua:911 "LSP[denols]" "client.request" 1 "textDocument/definition" {
position = {
character = 2,
line = 1
},
textDocument = {
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts"
}
} <function 1> 3
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:337 "rpc.send" {
id = 2,
jsonrpc = "2.0",
method = "textDocument/definition",
params = {
position = {
character = 2,
line = 1
},
textDocument = {
uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts"
}
}
}
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:435 "rpc.receive" {
id = 2,
jsonrpc = "2.0",
result = { {
targetRange = {
end = {
character = 1,
line = 663
},
start = {
character = 0,
line = 246
}
},
targetSelectionRange = {
end = {
character = 24,
line = 246
},
start = {
character = 13,
line = 246
}
},
targetUri = "deno:/https/deno.land/x/oak%40v9.0.1/application.ts"
} }
}
[DEBUG][2021-10-21 13:16:31] .../lua/vim/lsp.lua:911 "LSP[denols]" "client.request" 1 "deno/virtualTextDocument" {
textDocument = {
uri = "deno:/https/deno.land/x/oak%40v9.0.1/application.ts"
}
} <function 1> 3
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:337 "rpc.send" {
id = 3,
jsonrpc = "2.0",
method = "deno/virtualTextDocument",
params = {
textDocument = {
uri = "deno:/https/deno.land/x/oak%40v9.0.1/application.ts"
}
}
}
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:435 "rpc.receive" {
id = 3,
jsonrpc = "2.0",
result = "// Copyright 2018-2021 the oak authors. All rights reserved. MIT license.\n\nimport { Context } from \"./context.ts\";\nimport { assert, Status, STATUS_TEXT } from \"./deps.ts\";\nimport {\n hasNativeHttp,\n HttpServerNative,\n NativeRequest,\n} from \"./http_server_native.ts\";\nimport { HttpServerStd } from \"./http_server_std.ts\";\nimport type { ServerRequest, ServerResponse } from \"./http_server_std.ts\";\nimport { KeyStack } from \"./keyStack.ts\";\nimport { compose, Middleware } from \"./middleware.ts\";\nimport { cloneState } from \"./structured_clone.ts\";\nimport {\n FetchEventListenerObject,\n Key,\n Server,\n ServerConstructor,\n} from \"./types.d.ts\";\nimport { isConn } from \"./util.ts\";\n\nexport interface ListenOptionsBase extends Deno.ListenOptions {\n secure?: false;\n signal?: AbortSignal;\n}\n\nexport interface ListenOptionsTls extends Deno.ListenTlsOptions {\n /** Application-Layer Protocol Negotiation (ALPN) protocols to announce to\n * the client. If not specified, no ALPN extension will be included in the\n * TLS handshake.\n *\n * **NOTE** this is part of the native HTTP server in Deno 1.9 or later,\n * which requires the `--unstable` flag to be available.\n */\n alpnProtocols?: string[];\n secure: true;\n signal?: AbortSignal;\n}\n\nexport interface HandleMethod {\n /** Handle an individual server request, returning the server response. This\n * is similar to `.listen()`, but opening the connection and retrieving\n * requests are not the responsibility of the application. If the generated\n * context gets set to not to respond, then the method resolves with\n * `undefined`, otherwise it resolves with a request that is compatible with\n * `std/http/server`. */\n (\n request: ServerRequest,\n secure?: boolean,\n ): Promise<ServerResponse | undefined>;\n /** Handle an individual server request, returning the server response. This\n * is similar to `.listen()`, but opening the connection and retrieving\n * requests are not the responsibility of the application. If the generated\n * context gets set to not to respond, then the method resolves with\n * `undefined`, otherwise it resolves with a request that is compatible with\n * `std/http/server`. */\n (\n request: Request,\n conn?: Deno.Conn,\n secure?: boolean,\n ): Promise<Response | undefined>;\n}\n\nexport type ListenOptions = ListenOptionsTls | ListenOptionsBase;\n\ninterface ApplicationErrorEventListener<S extends AS, AS> {\n (evt: ApplicationErrorEvent<S, AS>): void | Promise<void>;\n}\n\ninterface ApplicationErrorEventListenerObject<S extends AS, AS> {\n handleEvent(evt: ApplicationErrorEvent<S, AS>): void | Promise<void>;\n}\n\ninterface ApplicationErrorEventInit<S extends AS, AS extends State>\n extends ErrorEventInit {\n context?: Context<S, AS>;\n}\n\ntype ApplicationErrorEventListenerOrEventListenerObject<S extends AS, AS> =\n | ApplicationErrorEventListener<S, AS>\n | ApplicationErrorEventListenerObject<S, AS>;\n\ninterface ApplicationListenEventListener {\n (evt: ApplicationListenEvent): void | Promise<void>;\n}\n\ninterface ApplicationListenEventListenerObject {\n handleEvent(evt: ApplicationListenEvent): void | Promise<void>;\n}\n\ninterface ApplicationListenEventInit extends EventInit {\n hostname: string;\n listener: Deno.Listener;\n port: number;\n secure: boolean;\n serverType: \"std\" | \"native\" | \"custom\";\n}\n\ntype ApplicationListenEventListenerOrEventListenerObject =\n | ApplicationListenEventListener\n | ApplicationListenEventListenerObject;\n\nexport interface ApplicationOptions<S> {\n /** Determine how when creating a new context, the state from the application\n * should be applied. A value of `\"clone\"` will set the state as a clone of\n * the app state. Any non-cloneable or non-enumerable properties will not be\n * copied. A value of `\"prototype\"` means that the application's state will be\n * used as the prototype of the the context's state, meaning shallow\n * properties on the context's state will not be reflected in the\n * application's state. A value of `\"alias\"` means that application's `.state`\n * and the context's `.state` will be a reference to the same object. A value\n * of `\"empty\"` will initialize the context's `.state` with an empty object.\n *\n * The default value is `\"clone\"`.\n */\n contextState?: \"clone\" | \"prototype\" | \"alias\" | \"empty\";\n\n /** An initial set of keys (or instance of `KeyGrip`) to be used for signing\n * cookies produced by the application. */\n keys?: KeyStack | Key[];\n\n /** If `true`, any errors handled by the application will be logged to the\n * stderr. If `false` nothing will be logged. The default is `true`.\n *\n * All errors are available as events on the application of type `\"error\"` and\n * can be accessed for custom logging/application management via adding an\n * event listener to the application:\n *\n * ```ts\n * const app = new Application({ logErrors: false });\n * app.addEventListener(\"error\", (evt) => {\n * // evt.error will contain what error was thrown\n * });\n * ```\n */\n logErrors?: boolean;\n\n /** If set to `true`, proxy headers will be trusted when processing requests.\n * This defaults to `false`. */\n proxy?: boolean;\n\n /** A server constructor to use instead of the default server for receiving\n * requests. When the native HTTP server is detected in the environment, then\n * the native server will be used, otherwise the `std/http` server will be\n * used. Passing either `HTTPServerStd` or `HTTPServerNative` will override\n * this behavior.\n */\n serverConstructor?: ServerConstructor<ServerRequest | NativeRequest>;\n\n /** The initial state object for the application, of which the type can be\n * used to infer the type of the state for both the application and any of the\n * application's context. */\n state?: S;\n}\n\nexport interface FetchEventHandlerOptions {\n /** Sets the applications `.proxy` value, which determines if proxy headers\n * are used when determining values in the request. This defaults to `true`.\n */\n proxy?: boolean;\n /** Determines if requests handled by the fetch event handler should be\n * treated as \"secure\" (e.g. served over HTTP). This defaults to `true`. */\n secure?: boolean;\n}\n\ninterface RequestState {\n handling: Set<Promise<void>>;\n closing: boolean;\n closed: boolean;\n server: Server<ServerRequest | NativeRequest>;\n}\n\n// deno-lint-ignore no-explicit-any\nexport type State = Record<string | number | symbol, any>;\n\nconst ADDR_REGEXP = /^\\[?([^\\]]*)\\]?:([0-9]{1,5})$/;\n\nexport class ApplicationErrorEvent<S extends AS, AS extends State>\n extends ErrorEvent {\n context?: Context<S, AS>;\n\n constructor(eventInitDict: ApplicationErrorEventInit<S, AS>) {\n super(\"error\", eventInitDict);\n this.context = eventInitDict.context;\n }\n}\n\nfunction logErrorListener<S extends AS, AS extends State>(\n { error, context }: ApplicationErrorEvent<S, AS>,\n) {\n if (error instanceof Error) {\n console.error(\n `[uncaught application error]: ${error.name} - ${error.message}`,\n );\n } else {\n console.error(`[uncaught application error]\\n`, error);\n }\n if (context) {\n let url: string;\n try {\n url = context.request.url.toString();\n } catch {\n url = \"[malformed url]\";\n }\n console.error(`\\nrequest:`, {\n url,\n method: context.request.method,\n hasBody: context.request.hasBody,\n });\n console.error(`response:`, {\n status: context.response.status,\n type: context.response.type,\n hasBody: !!context.response.body,\n writable: context.response.writable,\n });\n }\n if (error instanceof Error && error.stack) {\n console.error(`\\n${error.stack.split(\"\\n\").slice(1).join(\"\\n\")}`);\n }\n}\n\nexport class ApplicationListenEvent extends Event {\n hostname: string;\n listener: Deno.Listener;\n port: number;\n secure: boolean;\n serverType: \"std\" | \"native\" | \"custom\";\n\n constructor(eventInitDict: ApplicationListenEventInit) {\n super(\"listen\", eventInitDict);\n this.hostname = eventInitDict.hostname;\n this.listener = eventInitDict.listener;\n this.port = eventInitDict.port;\n this.secure = eventInitDict.secure;\n this.serverType = eventInitDict.serverType;\n }\n}\n\n/** A class which registers middleware (via `.use()`) and then processes\n * inbound requests against that middleware (via `.listen()`).\n *\n * The `context.state` can be typed via passing a generic argument when\n * constructing an instance of `Application`.\n */\n// deno-lint-ignore no-explicit-any\nexport class Application<AS extends State = Record<string, any>>\n extends EventTarget {\n #composedMiddleware?: (context: Context<AS, AS>) => Promise<unknown>;\n #contextState: \"clone\" | \"prototype\" | \"alias\" | \"empty\";\n #eventHandler?: FetchEventListenerObject;\n #keys?: KeyStack;\n #middleware: Middleware<State, Context<State, AS>>[] = [];\n #serverConstructor: ServerConstructor<ServerRequest | NativeRequest>;\n\n /** A set of keys, or an instance of `KeyStack` which will be used to sign\n * cookies read and set by the application to avoid tampering with the\n * cookies. */\n get keys(): KeyStack | Key[] | undefined {\n return this.#keys;\n }\n\n set keys(keys: KeyStack | Key[] | undefined) {\n if (!keys) {\n this.#keys = undefined;\n return;\n } else if (Array.isArray(keys)) {\n this.#keys = new KeyStack(keys);\n } else {\n this.#keys = keys;\n }\n }\n\n /** If `true`, proxy headers will be trusted when processing requests. This\n * defaults to `false`. */\n proxy: boolean;\n\n /** Generic state of the application, which can be specified by passing the\n * generic argument when constructing:\n *\n * const app = new Application<{ foo: string }>();\n *\n * Or can be contextually inferred based on setting an initial state object:\n *\n * const app = new Application({ state: { foo: \"bar\" } });\n *\n * When a new context is created, the application's state is cloned and the\n * state is unique to that request/response. Changes can be made to the\n * application state that will be shared with all contexts.\n */\n state: AS;\n\n constructor(options: ApplicationOptions<AS> = {}) {\n super();\n const {\n state,\n keys,\n proxy,\n serverConstructor = hasNativeHttp() ? HttpServerNative : HttpServerStd,\n contextState = \"clone\",\n logErrors = true,\n } = options;\n\n this.proxy = proxy ?? false;\n this.keys = keys;\n this.state = state ?? {} as AS;\n this.#serverConstructor = serverConstructor;\n this.#contextState = contextState;\n\n if (logErrors) {\n this.addEventListener(\"error\", logErrorListener);\n }\n }\n\n #getComposed(): ((context: Context<AS, AS>) => Promise<unknown>) {\n if (!this.#composedMiddleware) {\n this.#composedMiddleware = compose(this.#middleware);\n }\n return this.#composedMiddleware;\n }\n\n #getContextState(): AS {\n switch (this.#contextState) {\n case \"alias\":\n return this.state;\n case \"clone\":\n return cloneState(this.state);\n case \"empty\":\n return {} as AS;\n case \"prototype\":\n return Object.create(this.state);\n }\n }\n\n /** Deal with uncaught errors in either the middleware or sending the\n * response. */\n // deno-lint-ignore no-explicit-any\n #handleError(context: Context<AS>, error: any): void {\n if (!(error instanceof Error)) {\n error = new Error(`non-error thrown: ${JSON.stringify(error)}`);\n }\n const { message } = error;\n this.dispatchEvent(new ApplicationErrorEvent({ context, message, error }));\n if (!context.response.writable) {\n return;\n }\n for (const key of [...context.response.headers.keys()]) {\n context.response.headers.delete(key);\n }\n if (error.headers && error.headers instanceof Headers) {\n for (const [key, value] of error.headers) {\n context.response.headers.set(key, value);\n }\n }\n context.response.type = \"text\";\n const status: Status = context.response.status =\n Deno.errors && error instanceof Deno.errors.NotFound\n ? 404\n : error.status && typeof error.status === \"number\"\n ? error.status\n : 500;\n context.response.body = error.expose\n ? error.message\n : STATUS_TEXT.get(status);\n }\n\n /** Processing registered middleware on each request. */\n async #handleRequest(\n request: ServerRequest | NativeRequest,\n secure: boolean,\n state: RequestState,\n ): Promise<void> {\n const context = new Context(this, request, this.#getContextState(), secure);\n let resolve: () => void;\n const handlingPromise = new Promise<void>((res) => resolve = res);\n state.handling.add(handlingPromise);\n if (!state.closing && !state.closed) {\n try {\n await this.#getComposed()(context);\n } catch (err) {\n this.#handleError(context, err);\n }\n }\n if (context.respond === false) {\n context.response.destroy();\n resolve!();\n state.handling.delete(handlingPromise);\n return;\n }\n let closeResources = true;\n let response: Response | ServerResponse;\n try {\n if (request instanceof NativeRequest) {\n closeResources = false;\n response = await context.response.toDomResponse();\n } else {\n response = await context.response.toServerResponse();\n }\n } catch (err) {\n this.#handleError(context, err);\n if (request instanceof NativeRequest) {\n response = await context.response.toDomResponse();\n } else {\n response = await context.response.toServerResponse();\n }\n }\n assert(response);\n try {\n await request.respond(response as Response & ServerResponse);\n } catch (err) {\n this.#handleError(context, err);\n } finally {\n context.response.destroy(closeResources);\n resolve!();\n state.handling.delete(handlingPromise);\n if (state.closing) {\n state.server.close();\n state.closed = true;\n }\n }\n }\n\n /** Add an event listener for an `\"error\"` event which occurs when an\n * un-caught error occurs when processing the middleware or during processing\n * of the response. */\n addEventListener<S extends AS>(\n type: \"error\",\n listener: ApplicationErrorEventListenerOrEventListenerObject<S, AS> | null,\n options?: boolean | AddEventListenerOptions,\n ): void;\n /** Add an event listener for a `\"listen\"` event which occurs when the server\n * has successfully opened but before any requests start being processed. */\n addEventListener(\n type: \"listen\",\n listener: ApplicationListenEventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions,\n ): void;\n /** Add an event listener for an event. Currently valid event types are\n * `\"error\"` and `\"listen\"`. */\n addEventListener(\n type: \"error\" | \"listen\",\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions,\n ): void {\n super.addEventListener(type, listener, options);\n }\n\n /** **DEPRECATED**\n *\n * Deno Deploy now supports request events like the Deno CLI. Users should\n * use `app.listen()` just like if they were running on the Deno CLI for\n * Deploy apps. This method will be removed in future versions of oak.\n *\n * @deprecated This method will be removed in future versions of oak\n */\n fetchEventHandler(\n { proxy = true, secure = true }: FetchEventHandlerOptions = {},\n ): FetchEventListenerObject {\n if (this.#eventHandler) {\n return this.#eventHandler;\n }\n this.proxy = proxy;\n return this.#eventHandler = {\n handleEvent: async (requestEvent) => {\n let resolve: (response: Response) => void;\n // deno-lint-ignore no-explicit-any\n let reject: (reason: any) => void;\n const responsePromise = new Promise<Response>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const respondedPromise = requestEvent.respondWith(responsePromise);\n const response = await this.handle(\n requestEvent.request,\n undefined,\n secure,\n );\n if (response) {\n resolve!(response);\n } else {\n reject!(new Error(\"No response returned from app handler.\"));\n }\n try {\n await respondedPromise;\n } catch (error) {\n this.dispatchEvent(new ApplicationErrorEvent({ error }));\n }\n },\n };\n }\n\n /** Handle an individual server request, returning the server response. This\n * is similar to `.listen()`, but opening the connection and retrieving\n * requests are not the responsibility of the application. If the generated\n * context gets set to not to respond, then the method resolves with\n * `undefined`, otherwise it resolves with a request that is compatible with\n * `std/http/server`. */\n handle = (async (\n request: ServerRequest | Request,\n secureOrConn: Deno.Conn | boolean | undefined,\n secure: boolean | undefined = false,\n ): Promise<ServerResponse | Response | undefined> => {\n if (!this.#middleware.length) {\n throw new TypeError(\"There is no middleware to process requests.\");\n }\n let contextRequest: ServerRequest | NativeRequest;\n if (request instanceof Request) {\n assert(isConn(secureOrConn) || typeof secureOrConn === \"undefined\");\n contextRequest = new NativeRequest({\n request,\n respondWith() {\n return Promise.resolve(undefined);\n },\n }, { conn: secureOrConn });\n } else {\n assert(\n typeof secureOrConn === \"boolean\" ||\n typeof secureOrConn === \"undefined\",\n );\n secure = secureOrConn ?? false;\n contextRequest = request;\n }\n const context = new Context(\n this,\n contextRequest,\n this.#getContextState(),\n secure,\n );\n try {\n await this.#getComposed()(context);\n } catch (err) {\n this.#handleError(context, err);\n }\n if (context.respond === false) {\n context.response.destroy();\n return;\n }\n try {\n const response = contextRequest instanceof NativeRequest\n ? await context.response.toDomResponse()\n : await context.response.toServerResponse();\n context.response.destroy(false);\n return response;\n } catch (err) {\n this.#handleError(context, err);\n throw err;\n }\n }) as HandleMethod;\n\n /** Start listening for requests, processing registered middleware on each\n * request. If the options `.secure` is undefined or `false`, the listening\n * will be over HTTP. If the options `.secure` property is `true`, a\n * `.certFile` and a `.keyFile` property need to be supplied and requests\n * will be processed over HTTPS. */\n async listen(addr: string): Promise<void>;\n /** Start listening for requests, processing registered middleware on each\n * request. If the options `.secure` is undefined or `false`, the listening\n * will be over HTTP. If the options `.secure` property is `true`, a\n * `.certFile` and a `.keyFile` property need to be supplied and requests\n * will be processed over HTTPS. */\n async listen(options: ListenOptions): Promise<void>;\n async listen(options: string | ListenOptions): Promise<void> {\n if (!this.#middleware.length) {\n throw new TypeError(\"There is no middleware to process requests.\");\n }\n if (typeof options === \"string\") {\n const match = ADDR_REGEXP.exec(options);\n if (!match) {\n throw TypeError(`Invalid address passed: \"${options}\"`);\n }\n const [, hostname, portStr] = match;\n options = { hostname, port: parseInt(portStr, 10) };\n }\n const server = new this.#serverConstructor(this, options);\n const { signal } = options;\n const state = {\n closed: false,\n closing: false,\n handling: new Set<Promise<void>>(),\n server,\n };\n if (signal) {\n signal.addEventListener(\"abort\", () => {\n if (!state.handling.size) {\n server.close();\n state.closed = true;\n }\n state.closing = true;\n });\n }\n const { secure = false } = options;\n const serverType = server instanceof HttpServerStd\n ? \"std\"\n : server instanceof HttpServerNative\n ? \"native\"\n : \"custom\";\n const listener = server.listen();\n const { hostname, port } = listener.addr as Deno.NetAddr;\n this.dispatchEvent(\n new ApplicationListenEvent({\n hostname,\n listener,\n port,\n secure,\n serverType,\n }),\n );\n try {\n for await (const request of server) {\n this.#handleRequest(request, secure, state);\n }\n await Promise.all(state.handling);\n } catch (error) {\n const message = error instanceof Error\n ? error.message\n : \"Application Error\";\n this.dispatchEvent(\n new ApplicationErrorEvent({ message, error }),\n );\n }\n }\n\n /** Register middleware to be used with the application. Middleware will\n * be processed in the order it is added, but middleware can control the flow\n * of execution via the use of the `next()` function that the middleware\n * function will be called with. The `context` object provides information\n * about the current state of the application.\n *\n * Basic usage:\n *\n * ```ts\n * const import { Application } from \"https://deno.land/x/oak/mod.ts\";\n *\n * const app = new Application();\n *\n * app.use((ctx, next) => {\n * ctx.request; // contains request information\n * ctx.response; // setups up information to use in the response;\n * await next(); // manages the flow control of the middleware execution\n * });\n *\n * await app.listen({ port: 80 });\n * ```\n */\n use<S extends State = AS>(\n middleware: Middleware<S, Context<S, AS>>,\n ...middlewares: Middleware<S, Context<S, AS>>[]\n ): Application<S extends AS ? S : (S & AS)>;\n use<S extends State = AS>(\n ...middleware: Middleware<S, Context<S, AS>>[]\n ): Application<S extends AS ? S : (S & AS)> {\n this.#middleware.push(...middleware);\n this.#composedMiddleware = undefined;\n // deno-lint-ignore no-explicit-any\n return this as Application<any>;\n }\n\n [Symbol.for(\"Deno.customInspect\")](inspect: (value: unknown) => string) {\n const { keys, proxy, state } = this;\n return `${this.constructor.name} ${\n inspect({ \"#middleware\": this.#middleware, keys, proxy, state })\n }`;\n }\n}\n"
}
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:337 "rpc.send" {
jsonrpc = "2.0",
method = "textDocument/didOpen",
params = {
textDocument = {
languageId = "typescript",
text = "// Copyright 2018-2021 the oak authors. All rights reserved. MIT license.\n\nimport { Context } from \"./context.ts\";\nimport { assert, Status, STATUS_TEXT } from \"./deps.ts\";\nimport {\n hasNativeHttp,\n HttpServerNative,\n NativeRequest,\n} from \"./http_server_native.ts\";\nimport { HttpServerStd } from \"./http_server_std.ts\";\nimport type { ServerRequest, ServerResponse } from \"./http_server_std.ts\";\nimport { KeyStack } from \"./keyStack.ts\";\nimport { compose, Middleware } from \"./middleware.ts\";\nimport { cloneState } from \"./structured_clone.ts\";\nimport {\n FetchEventListenerObject,\n Key,\n Server,\n ServerConstructor,\n} from \"./types.d.ts\";\nimport { isConn } from \"./util.ts\";\n\nexport interface ListenOptionsBase extends Deno.ListenOptions {\n secure?: false;\n signal?: AbortSignal;\n}\n\nexport interface ListenOptionsTls extends Deno.ListenTlsOptions {\n /** Application-Layer Protocol Negotiation (ALPN) protocols to announce to\n * the client. If not specified, no ALPN extension will be included in the\n * TLS handshake.\n *\n * **NOTE** this is part of the native HTTP server in Deno 1.9 or later,\n * which requires the `--unstable` flag to be available.\n */\n alpnProtocols?: string[];\n secure: true;\n signal?: AbortSignal;\n}\n\nexport interface HandleMethod {\n /** Handle an individual server request, returning the server response. This\n * is similar to `.listen()`, but opening the connection and retrieving\n * requests are not the responsibility of the application. If the generated\n * context gets set to not to respond, then the method resolves with\n * `undefined`, otherwise it resolves with a request that is compatible with\n * `std/http/server`. */\n (\n request: ServerRequest,\n secure?: boolean,\n ): Promise<ServerResponse | undefined>;\n /** Handle an individual server request, returning the server response. This\n * is similar to `.listen()`, but opening the connection and retrieving\n * requests are not the responsibility of the application. If the generated\n * context gets set to not to respond, then the method resolves with\n * `undefined`, otherwise it resolves with a request that is compatible with\n * `std/http/server`. */\n (\n request: Request,\n conn?: Deno.Conn,\n secure?: boolean,\n ): Promise<Response | undefined>;\n}\n\nexport type ListenOptions = ListenOptionsTls | ListenOptionsBase;\n\ninterface ApplicationErrorEventListener<S extends AS, AS> {\n (evt: ApplicationErrorEvent<S, AS>): void | Promise<void>;\n}\n\ninterface ApplicationErrorEventListenerObject<S extends AS, AS> {\n handleEvent(evt: ApplicationErrorEvent<S, AS>): void | Promise<void>;\n}\n\ninterface ApplicationErrorEventInit<S extends AS, AS extends State>\n extends ErrorEventInit {\n context?: Context<S, AS>;\n}\n\ntype ApplicationErrorEventListenerOrEventListenerObject<S extends AS, AS> =\n | ApplicationErrorEventListener<S, AS>\n | ApplicationErrorEventListenerObject<S, AS>;\n\ninterface ApplicationListenEventListener {\n (evt: ApplicationListenEvent): void | Promise<void>;\n}\n\ninterface ApplicationListenEventListenerObject {\n handleEvent(evt: ApplicationListenEvent): void | Promise<void>;\n}\n\ninterface ApplicationListenEventInit extends EventInit {\n hostname: string;\n listener: Deno.Listener;\n port: number;\n secure: boolean;\n serverType: \"std\" | \"native\" | \"custom\";\n}\n\ntype ApplicationListenEventListenerOrEventListenerObject =\n | ApplicationListenEventListener\n | ApplicationListenEventListenerObject;\n\nexport interface ApplicationOptions<S> {\n /** Determine how when creating a new context, the state from the application\n * should be applied. A value of `\"clone\"` will set the state as a clone of\n * the app state. Any non-cloneable or non-enumerable properties will not be\n * copied. A value of `\"prototype\"` means that the application's state will be\n * used as the prototype of the the context's state, meaning shallow\n * properties on the context's state will not be reflected in the\n * application's state. A value of `\"alias\"` means that application's `.state`\n * and the context's `.state` will be a reference to the same object. A value\n * of `\"empty\"` will initialize the context's `.state` with an empty object.\n *\n * The default value is `\"clone\"`.\n */\n contextState?: \"clone\" | \"prototype\" | \"alias\" | \"empty\";\n\n /** An initial set of keys (or instance of `KeyGrip`) to be used for signing\n * cookies produced by the application. */\n keys?: KeyStack | Key[];\n\n /** If `true`, any errors handled by the application will be logged to the\n * stderr. If `false` nothing will be logged. The default is `true`.\n *\n * All errors are available as events on the application of type `\"error\"` and\n * can be accessed for custom logging/application management via adding an\n * event listener to the application:\n *\n * ```ts\n * const app = new Application({ logErrors: false });\n * app.addEventListener(\"error\", (evt) => {\n * // evt.error will contain what error was thrown\n * });\n * ```\n */\n logErrors?: boolean;\n\n /** If set to `true`, proxy headers will be trusted when processing requests.\n * This defaults to `false`. */\n proxy?: boolean;\n\n /** A server constructor to use instead of the default server for receiving\n * requests. When the native HTTP server is detected in the environment, then\n * the native server will be used, otherwise the `std/http` server will be\n * used. Passing either `HTTPServerStd` or `HTTPServerNative` will override\n * this behavior.\n */\n serverConstructor?: ServerConstructor<ServerRequest | NativeRequest>;\n\n /** The initial state object for the application, of which the type can be\n * used to infer the type of the state for both the application and any of the\n * application's context. */\n state?: S;\n}\n\nexport interface FetchEventHandlerOptions {\n /** Sets the applications `.proxy` value, which determines if proxy headers\n * are used when determining values in the request. This defaults to `true`.\n */\n proxy?: boolean;\n /** Determines if requests handled by the fetch event handler should be\n * treated as \"secure\" (e.g. served over HTTP). This defaults to `true`. */\n secure?: boolean;\n}\n\ninterface RequestState {\n handling: Set<Promise<void>>;\n closing: boolean;\n closed: boolean;\n server: Server<ServerRequest | NativeRequest>;\n}\n\n// deno-lint-ignore no-explicit-any\nexport type State = Record<string | number | symbol, any>;\n\nconst ADDR_REGEXP = /^\\[?([^\\]]*)\\]?:([0-9]{1,5})$/;\n\nexport class ApplicationErrorEvent<S extends AS, AS extends State>\n extends ErrorEvent {\n context?: Context<S, AS>;\n\n constructor(eventInitDict: ApplicationErrorEventInit<S, AS>) {\n super(\"error\", eventInitDict);\n this.context = eventInitDict.context;\n }\n}\n\nfunction logErrorListener<S extends AS, AS extends State>(\n { error, context }: ApplicationErrorEvent<S, AS>,\n) {\n if (error instanceof Error) {\n console.error(\n `[uncaught application error]: ${error.name} - ${error.message}`,\n );\n } else {\n console.error(`[uncaught application error]\\n`, error);\n }\n if (context) {\n let url: string;\n try {\n url = context.request.url.toString();\n } catch {\n url = \"[malformed url]\";\n }\n console.error(`\\nrequest:`, {\n url,\n method: context.request.method,\n hasBody: context.request.hasBody,\n });\n console.error(`response:`, {\n status: context.response.status,\n type: context.response.type,\n hasBody: !!context.response.body,\n writable: context.response.writable,\n });\n }\n if (error instanceof Error && error.stack) {\n console.error(`\\n${error.stack.split(\"\\n\").slice(1).join(\"\\n\")}`);\n }\n}\n\nexport class ApplicationListenEvent extends Event {\n hostname: string;\n listener: Deno.Listener;\n port: number;\n secure: boolean;\n serverType: \"std\" | \"native\" | \"custom\";\n\n constructor(eventInitDict: ApplicationListenEventInit) {\n super(\"listen\", eventInitDict);\n this.hostname = eventInitDict.hostname;\n this.listener = eventInitDict.listener;\n this.port = eventInitDict.port;\n this.secure = eventInitDict.secure;\n this.serverType = eventInitDict.serverType;\n }\n}\n\n/** A class which registers middleware (via `.use()`) and then processes\n * inbound requests against that middleware (via `.listen()`).\n *\n * The `context.state` can be typed via passing a generic argument when\n * constructing an instance of `Application`.\n */\n// deno-lint-ignore no-explicit-any\nexport class Application<AS extends State = Record<string, any>>\n extends EventTarget {\n #composedMiddleware?: (context: Context<AS, AS>) => Promise<unknown>;\n #contextState: \"clone\" | \"prototype\" | \"alias\" | \"empty\";\n #eventHandler?: FetchEventListenerObject;\n #keys?: KeyStack;\n #middleware: Middleware<State, Context<State, AS>>[] = [];\n #serverConstructor: ServerConstructor<ServerRequest | NativeRequest>;\n\n /** A set of keys, or an instance of `KeyStack` which will be used to sign\n * cookies read and set by the application to avoid tampering with the\n * cookies. */\n get keys(): KeyStack | Key[] | undefined {\n return this.#keys;\n }\n\n set keys(keys: KeyStack | Key[] | undefined) {\n if (!keys) {\n this.#keys = undefined;\n return;\n } else if (Array.isArray(keys)) {\n this.#keys = new KeyStack(keys);\n } else {\n this.#keys = keys;\n }\n }\n\n /** If `true`, proxy headers will be trusted when processing requests. This\n * defaults to `false`. */\n proxy: boolean;\n\n /** Generic state of the application, which can be specified by passing the\n * generic argument when constructing:\n *\n * const app = new Application<{ foo: string }>();\n *\n * Or can be contextually inferred based on setting an initial state object:\n *\n * const app = new Application({ state: { foo: \"bar\" } });\n *\n * When a new context is created, the application's state is cloned and the\n * state is unique to that request/response. Changes can be made to the\n * application state that will be shared with all contexts.\n */\n state: AS;\n\n constructor(options: ApplicationOptions<AS> = {}) {\n super();\n const {\n state,\n keys,\n proxy,\n serverConstructor = hasNativeHttp() ? HttpServerNative : HttpServerStd,\n contextState = \"clone\",\n logErrors = true,\n } = options;\n\n this.proxy = proxy ?? false;\n this.keys = keys;\n this.state = state ?? {} as AS;\n this.#serverConstructor = serverConstructor;\n this.#contextState = contextState;\n\n if (logErrors) {\n this.addEventListener(\"error\", logErrorListener);\n }\n }\n\n #getComposed(): ((context: Context<AS, AS>) => Promise<unknown>) {\n if (!this.#composedMiddleware) {\n this.#composedMiddleware = compose(this.#middleware);\n }\n return this.#composedMiddleware;\n }\n\n #getContextState(): AS {\n switch (this.#contextState) {\n case \"alias\":\n return this.state;\n case \"clone\":\n return cloneState(this.state);\n case \"empty\":\n return {} as AS;\n case \"prototype\":\n return Object.create(this.state);\n }\n }\n\n /** Deal with uncaught errors in either the middleware or sending the\n * response. */\n // deno-lint-ignore no-explicit-any\n #handleError(context: Context<AS>, error: any): void {\n if (!(error instanceof Error)) {\n error = new Error(`non-error thrown: ${JSON.stringify(error)}`);\n }\n const { message } = error;\n this.dispatchEvent(new ApplicationErrorEvent({ context, message, error }));\n if (!context.response.writable) {\n return;\n }\n for (const key of [...context.response.headers.keys()]) {\n context.response.headers.delete(key);\n }\n if (error.headers && error.headers instanceof Headers) {\n for (const [key, value] of error.headers) {\n context.response.headers.set(key, value);\n }\n }\n context.response.type = \"text\";\n const status: Status = context.response.status =\n Deno.errors && error instanceof Deno.errors.NotFound\n ? 404\n : error.status && typeof error.status === \"number\"\n ? error.status\n : 500;\n context.response.body = error.expose\n ? error.message\n : STATUS_TEXT.get(status);\n }\n\n /** Processing registered middleware on each request. */\n async #handleRequest(\n request: ServerRequest | NativeRequest,\n secure: boolean,\n state: RequestState,\n ): Promise<void> {\n const context = new Context(this, request, this.#getContextState(), secure);\n let resolve: () => void;\n const handlingPromise = new Promise<void>((res) => resolve = res);\n state.handling.add(handlingPromise);\n if (!state.closing && !state.closed) {\n try {\n await this.#getComposed()(context);\n } catch (err) {\n this.#handleError(context, err);\n }\n }\n if (context.respond === false) {\n context.response.destroy();\n resolve!();\n state.handling.delete(handlingPromise);\n return;\n }\n let closeResources = true;\n let response: Response | ServerResponse;\n try {\n if (request instanceof NativeRequest) {\n closeResources = false;\n response = await context.response.toDomResponse();\n } else {\n response = await context.response.toServerResponse();\n }\n } catch (err) {\n this.#handleError(context, err);\n if (request instanceof NativeRequest) {\n response = await context.response.toDomResponse();\n } else {\n response = await context.response.toServerResponse();\n }\n }\n assert(response);\n try {\n await request.respond(response as Response & ServerResponse);\n } catch (err) {\n this.#handleError(context, err);\n } finally {\n context.response.destroy(closeResources);\n resolve!();\n state.handling.delete(handlingPromise);\n if (state.closing) {\n state.server.close();\n state.closed = true;\n }\n }\n }\n\n /** Add an event listener for an `\"error\"` event which occurs when an\n * un-caught error occurs when processing the middleware or during processing\n * of the response. */\n addEventListener<S extends AS>(\n type: \"error\",\n listener: ApplicationErrorEventListenerOrEventListenerObject<S, AS> | null,\n options?: boolean | AddEventListenerOptions,\n ): void;\n /** Add an event listener for a `\"listen\"` event which occurs when the server\n * has successfully opened but before any requests start being processed. */\n addEventListener(\n type: \"listen\",\n listener: ApplicationListenEventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions,\n ): void;\n /** Add an event listener for an event. Currently valid event types are\n * `\"error\"` and `\"listen\"`. */\n addEventListener(\n type: \"error\" | \"listen\",\n listener: EventListenerOrEventListenerObject | null,\n options?: boolean | AddEventListenerOptions,\n ): void {\n super.addEventListener(type, listener, options);\n }\n\n /** **DEPRECATED**\n *\n * Deno Deploy now supports request events like the Deno CLI. Users should\n * use `app.listen()` just like if they were running on the Deno CLI for\n * Deploy apps. This method will be removed in future versions of oak.\n *\n * @deprecated This method will be removed in future versions of oak\n */\n fetchEventHandler(\n { proxy = true, secure = true }: FetchEventHandlerOptions = {},\n ): FetchEventListenerObject {\n if (this.#eventHandler) {\n return this.#eventHandler;\n }\n this.proxy = proxy;\n return this.#eventHandler = {\n handleEvent: async (requestEvent) => {\n let resolve: (response: Response) => void;\n // deno-lint-ignore no-explicit-any\n let reject: (reason: any) => void;\n const responsePromise = new Promise<Response>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const respondedPromise = requestEvent.respondWith(responsePromise);\n const response = await this.handle(\n requestEvent.request,\n undefined,\n secure,\n );\n if (response) {\n resolve!(response);\n } else {\n reject!(new Error(\"No response returned from app handler.\"));\n }\n try {\n await respondedPromise;\n } catch (error) {\n this.dispatchEvent(new ApplicationErrorEvent({ error }));\n }\n },\n };\n }\n\n /** Handle an individual server request, returning the server response. This\n * is similar to `.listen()`, but opening the connection and retrieving\n * requests are not the responsibility of the application. If the generated\n * context gets set to not to respond, then the method resolves with\n * `undefined`, otherwise it resolves with a request that is compatible with\n * `std/http/server`. */\n handle = (async (\n request: ServerRequest | Request,\n secureOrConn: Deno.Conn | boolean | undefined,\n secure: boolean | undefined = false,\n ): Promise<ServerResponse | Response | undefined> => {\n if (!this.#middleware.length) {\n throw new TypeError(\"There is no middleware to process requests.\");\n }\n let contextRequest: ServerRequest | NativeRequest;\n if (request instanceof Request) {\n assert(isConn(secureOrConn) || typeof secureOrConn === \"undefined\");\n contextRequest = new NativeRequest({\n request,\n respondWith() {\n return Promise.resolve(undefined);\n },\n }, { conn: secureOrConn });\n } else {\n assert(\n typeof secureOrConn === \"boolean\" ||\n typeof secureOrConn === \"undefined\",\n );\n secure = secureOrConn ?? false;\n contextRequest = request;\n }\n const context = new Context(\n this,\n contextRequest,\n this.#getContextState(),\n secure,\n );\n try {\n await this.#getComposed()(context);\n } catch (err) {\n this.#handleError(context, err);\n }\n if (context.respond === false) {\n context.response.destroy();\n return;\n }\n try {\n const response = contextRequest instanceof NativeRequest\n ? await context.response.toDomResponse()\n : await context.response.toServerResponse();\n context.response.destroy(false);\n return response;\n } catch (err) {\n this.#handleError(context, err);\n throw err;\n }\n }) as HandleMethod;\n\n /** Start listening for requests, processing registered middleware on each\n * request. If the options `.secure` is undefined or `false`, the listening\n * will be over HTTP. If the options `.secure` property is `true`, a\n * `.certFile` and a `.keyFile` property need to be supplied and requests\n * will be processed over HTTPS. */\n async listen(addr: string): Promise<void>;\n /** Start listening for requests, processing registered middleware on each\n * request. If the options `.secure` is undefined or `false`, the listening\n * will be over HTTP. If the options `.secure` property is `true`, a\n * `.certFile` and a `.keyFile` property need to be supplied and requests\n * will be processed over HTTPS. */\n async listen(options: ListenOptions): Promise<void>;\n async listen(options: string | ListenOptions): Promise<void> {\n if (!this.#middleware.length) {\n throw new TypeError(\"There is no middleware to process requests.\");\n }\n if (typeof options === \"string\") {\n const match = ADDR_REGEXP.exec(options);\n if (!match) {\n throw TypeError(`Invalid address passed: \"${options}\"`);\n }\n const [, hostname, portStr] = match;\n options = { hostname, port: parseInt(portStr, 10) };\n }\n const server = new this.#serverConstructor(this, options);\n const { signal } = options;\n const state = {\n closed: false,\n closing: false,\n handling: new Set<Promise<void>>(),\n server,\n };\n if (signal) {\n signal.addEventListener(\"abort\", () => {\n if (!state.handling.size) {\n server.close();\n state.closed = true;\n }\n state.closing = true;\n });\n }\n const { secure = false } = options;\n const serverType = server instanceof HttpServerStd\n ? \"std\"\n : server instanceof HttpServerNative\n ? \"native\"\n : \"custom\";\n const listener = server.listen();\n const { hostname, port } = listener.addr as Deno.NetAddr;\n this.dispatchEvent(\n new ApplicationListenEvent({\n hostname,\n listener,\n port,\n secure,\n serverType,\n }),\n );\n try {\n for await (const request of server) {\n this.#handleRequest(request, secure, state);\n }\n await Promise.all(state.handling);\n } catch (error) {\n const message = error instanceof Error\n ? error.message\n : \"Application Error\";\n this.dispatchEvent(\n new ApplicationErrorEvent({ message, error }),\n );\n }\n }\n\n /** Register middleware to be used with the application. Middleware will\n * be processed in the order it is added, but middleware can control the flow\n * of execution via the use of the `next()` function that the middleware\n * function will be called with. The `context` object provides information\n * about the current state of the application.\n *\n * Basic usage:\n *\n * ```ts\n * const import { Application } from \"https://deno.land/x/oak/mod.ts\";\n *\n * const app = new Application();\n *\n * app.use((ctx, next) => {\n * ctx.request; // contains request information\n * ctx.response; // setups up information to use in the response;\n * await next(); // manages the flow control of the middleware execution\n * });\n *\n * await app.listen({ port: 80 });\n * ```\n */\n use<S extends State = AS>(\n middleware: Middleware<S, Context<S, AS>>,\n ...middlewares: Middleware<S, Context<S, AS>>[]\n ): Application<S extends AS ? S : (S & AS)>;\n use<S extends State = AS>(\n ...middleware: Middleware<S, Context<S, AS>>[]\n ): Application<S extends AS ? S : (S & AS)> {\n this.#middleware.push(...middleware);\n this.#composedMiddleware = undefined;\n // deno-lint-ignore no-explicit-any\n return this as Application<any>;\n }\n\n [Symbol.for(\"Deno.customInspect\")](inspect: (value: unknown) => string) {\n const { keys, proxy, state } = this;\n return `${this.constructor.name} ${\n inspect({ \"#middleware\": this.#middleware, keys, proxy, state })\n }`;\n }\n}\n\n",
uri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts",
version = 0
}
}
}
[TRACE][2021-10-21 13:16:31] ...lsp/handlers.lua:432 "default_handler" "textDocument/definition" {
ctx = '{\n bufnr = 3,\n client_id = 1,\n method = "textDocument/definition",\n params = {\n position = {\n character = 2,\n line = 1\n },\n textDocument = {\n uri = "file:///Users/robotx/dev/tmp/deno_oak_test/server.ts"\n }\n }\n}',
result = { {
targetRange = {
end = {
character = 1,
line = 663
},
start = {
character = 0,
line = 246
}
},
targetSelectionRange = {
end = {
character = 24,
line = 246
},
start = {
character = 13,
line = 246
}
},
targetUri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts",
uri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts"
} }
}
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:435 "rpc.receive" {
id = 1,
jsonrpc = "2.0",
method = "workspace/configuration",
params = {
items = { {
scopeUri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts",
section = "deno"
} }
}
}
[TRACE][2021-10-21 13:16:31] .../lua/vim/lsp.lua:705 "server_request" "workspace/configuration" {
items = { {
scopeUri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts",
section = "deno"
} }
}
[TRACE][2021-10-21 13:16:31] .../lua/vim/lsp.lua:708 "server_request: found handler for" "workspace/configuration"
[TRACE][2021-10-21 13:16:31] ...lsp/handlers.lua:432 "default_handler" "workspace/configuration" {
ctx = '{\n client_id = 1,\n method = "workspace/configuration"\n}',
result = {
items = { {
scopeUri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts",
section = "deno"
} }
}
}
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:445 "server_request: callback result" {
result = { vim.NIL },
status = true
}
[DEBUG][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:337 "rpc.send" {
id = 1,
jsonrpc = "2.0",
result = { vim.NIL }
}
[ERROR][2021-10-21 13:16:31] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" "Error converting specifier settings: invalid type: null, expected struct SpecifierSettings\n"
[DEBUG][2021-10-21 13:16:32] .../lua/vim/lsp.lua:911 "LSP[denols]" "client.request" 1 "textDocument/hover" {
position = {
character = 13,
line = 246
},
textDocument = {
uri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts"
}
} <function 1> 4
[DEBUG][2021-10-21 13:16:32] .../vim/lsp/rpc.lua:337 "rpc.send" {
id = 4,
jsonrpc = "2.0",
method = "textDocument/hover",
params = {
position = {
character = 13,
line = 246
},
textDocument = {
uri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts"
}
}
}
[DEBUG][2021-10-21 13:16:32] .../vim/lsp/rpc.lua:435 "rpc.receive" {
error = {
code = -32602,
message = "An unexpected specifier (deno://https/deno.land/x/oak%40v9.0.1/application.ts) was provided."
},
id = 4,
jsonrpc = "2.0"
}
[TRACE][2021-10-21 13:16:32] ...lsp/handlers.lua:432 "default_handler" "textDocument/hover" {
ctx = '{\n bufnr = 4,\n client_id = 1,\n method = "textDocument/hover",\n params = {\n position = {\n character = 13,\n line = 246\n },\n textDocument = {\n uri = "deno://https/deno.land/x/oak%40v9.0.1/application.ts"\n }\n }\n}',
err = {
code = -32602,
message = "An unexpected specifier (deno://https/deno.land/x/oak%40v9.0.1/application.ts) was provided.",
<metatable> = {
__tostring = <function 1>
}
}
}
[INFO][2021-10-21 13:16:38] .../lua/vim/lsp.lua:1230 "exit_handler" { {
_on_attach = <function 1>,
cancel_request = <function 2>,
config = {
_on_attach = <function 3>,
autostart = true,
capabilities = {
callHierarchy = {
dynamicRegistration = false
},
textDocument = {
codeAction = {
codeActionLiteralSupport = {
codeActionKind = {
valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports" }
}
},
dataSupport = true,
dynamicRegistration = false,
resolveSupport = {
properties = { "edit" }
}
},
completion = {
completionItem = {
commitCharactersSupport = false,
deprecatedSupport = false,
documentationFormat = { "markdown", "plaintext" },
preselectSupport = false,
snippetSupport = false
},
completionItemKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }
},
contextSupport = false,
dynamicRegistration = false
},
declaration = {
linkSupport = true
},
definition = {
linkSupport = true
},
documentHighlight = {
dynamicRegistration = false
},
documentSymbol = {
dynamicRegistration = false,
hierarchicalDocumentSymbolSupport = true,
symbolKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }
}
},
hover = {
contentFormat = { "markdown", "plaintext" },
dynamicRegistration = false
},
implementation = {
linkSupport = true
},
publishDiagnostics = {
relatedInformation = true,
tagSupport = {
valueSet = { 1, 2 }
}
},
references = {
dynamicRegistration = false
},
rename = {
dynamicRegistration = false,
prepareSupport = true
},
signatureHelp = {
dynamicRegistration = false,
signatureInformation = {
activeParameterSupport = true,
documentationFormat = { "markdown", "plaintext" },
parameterInformation = {
labelOffsetSupport = true
}
}
},
synchronization = {
didSave = true,
dynamicRegistration = false,
willSave = false,
willSaveWaitUntil = false
},
typeDefinition = {
linkSupport = true
}
},
window = {
showDocument = {
support = false
},
showMessage = {
messageActionItem = {
additionalPropertiesSupport = false
}
},
workDoneProgress = true
},
workspace = {
applyEdit = true,
configuration = true,
symbol = {
dynamicRegistration = false,
hierarchicalWorkspaceSymbolSupport = true,
symbolKind = {
valueSet = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }
}
},
workspaceEdit = {
resourceOperations = { "rename", "create", "delete" }
},
workspaceFolders = true
}
},
cmd = { "deno", "lsp" },
filetypes = { "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx" },
flags = {},
get_language_id = <function 4>,
handlers = <1>{
["textDocument/definition"] = <function 5>,
["textDocument/references"] = <function 6>
},
init_options = {
enable = true,
lint = false,
unstable = false
},
log_level = 2,
message_level = 2,
name = "denols",
on_attach = <function 7>,
on_exit = <function 8>,
on_init = <function 9>,
root_dir = "/Users/robotx/dev/tmp/deno_oak_test",
settings = vim.empty_dict(),
workspace_folders = <2>{ {
name = "/Users/robotx/dev/tmp/deno_oak_test",
uri = "file:///Users/robotx/dev/tmp/deno_oak_test"
} },
<metatable> = <3>{
__tostring = <function 10>
}
},
handlers = <table 1>,
id = 1,
initialized = true,
is_stopped = <function 11>,
messages = {
messages = {},
name = "denols",
progress = {},
status = {}
},
name = "denols",
notify = <function 12>,
offset_encoding = "utf-16",
request = <function 13>,
request_sync = <function 14>,
resolved_capabilities = {
call_hierarchy = true,
code_action = <4>{
codeActionKinds = { "quickfix", "refactor", "refactor.extract.function", "refactor.extract.constant", "refactor.extract.type", "refactor.extract.interface", "refactor.move.newFile", "refactor.rewrite.import", "refactor.rewrite.export", "refactor.rewrite.arrow.braces", "refactor.rewrite.parameters.toDestructured", "refactor.rewrite.property.generateAccessors" },
resolveProvider = true
},
code_lens = true,
code_lens_resolve = true,
completion = true,
declaration = false,
document_formatting = true,
document_highlight = true,
document_range_formatting = false,
document_symbol = true,
execute_command = false,
find_references = true,
goto_definition = true,
hover = true,
implementation = true,
rename = true,
signature_help = true,
signature_help_trigger_characters = <5>{ ",", "(", "<" },
text_document_did_change = 2,
text_document_open_close = true,
text_document_save = <6>vim.empty_dict(),
text_document_save_include_text = false,
text_document_will_save = false,
text_document_will_save_wait_until = false,
type_definition = false,
workspace_folder_properties = {
changeNotifications = false,
supported = true
},
workspace_symbol = false
},
rpc = {
handle = <userdata 1>,
notify = <function 15>,
pid = 25130,
request = <function 16>
},
server_capabilities = {
callHierarchyProvider = true,
codeActionProvider = <table 4>,
codeLensProvider = {
resolveProvider = true
},
completionProvider = {
allCommitCharacters = { ".", ",", ";", "(" },
resolveProvider = true,
triggerCharacters = { ".", '"', "'", "`", "/", "@", "<", "#" }
},
definitionProvider = true,
documentFormattingProvider = true,
documentHighlightProvider = true,
documentSymbolProvider = true,
foldingRangeProvider = true,
hoverProvider = true,
implementationProvider = true,
referencesProvider = true,
renameProvider = true,
selectionRangeProvider = true,
semanticTokensProvider = {
full = true,
legend = {
tokenModifiers = { "declaration", "static", "async", "readonly", "defaultLibrary", "local" },
tokenTypes = { "class", "enum", "interface", "namespace", "typeParameter", "type", "parameter", "variable", "enumMember", "property", "function", "method" }
},
range = true
},
signatureHelpProvider = {
retriggerCharacters = { ")" },
triggerCharacters = <table 5>
},
textDocumentSync = {
change = 2,
openClose = true,
save = <table 6>
},
workspace = {
workspaceFolders = {
supported = true
}
}
},
stop = <function 17>,
supports_method = <function 18>,
workspaceFolders = <table 2>,
workspace_did_change_configuration = <function 19>
} }
[DEBUG][2021-10-21 13:16:38] .../vim/lsp/rpc.lua:337 "rpc.send" {
id = 5,
jsonrpc = "2.0",
method = "shutdown"
}
[ERROR][2021-10-21 13:16:38] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" "shutdown request received, shutting down\n"
[DEBUG][2021-10-21 13:16:38] .../vim/lsp/rpc.lua:435 "rpc.receive" {
id = 5,
jsonrpc = "2.0"
}
[DEBUG][2021-10-21 13:16:38] .../vim/lsp/rpc.lua:337 "rpc.send" {
jsonrpc = "2.0",
method = "exit"
}
[ERROR][2021-10-21 13:16:38] .../vim/lsp/rpc.lua:401 "rpc" "deno" "stderr" "exit notification received, stopping\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment