1+ /**
2+ * Implementation of smuggler APIs like @see StorageApi which interact with a
3+ * cloud-hosted infrastructure to perform their job.
4+ */
5+
16import {
27 AccountInfo ,
38 Ack ,
@@ -7,18 +12,14 @@ import {
712 GenerateBlobIndexResponse ,
813 GetUserExternalAssociationsResponse ,
914 NewNodeResponse ,
10- Nid ,
1115 NodeAttrsSearchRequest ,
1216 NodeAttrsSearchResponse ,
1317 NodeBatch ,
1418 NodeCreateRequestBody ,
1519 NodeCreatedVia ,
1620 NodeEdges ,
17- NodeExtattrs ,
18- NodeIndexText ,
1921 NodePatchRequest ,
2022 NodeTextData ,
21- NodeType ,
2223 OriginId ,
2324 TEdge ,
2425 TNode ,
@@ -29,7 +30,17 @@ import {
2930 UserExternalPipelineId ,
3031 UserExternalPipelineIngestionProgress ,
3132} from './types'
32-
33+ import type {
34+ UniqueNodeLookupKey ,
35+ NonUniqueNodeLookupKey ,
36+ NodeLookupKey ,
37+ CreateNodeArgs ,
38+ GetNodeSliceArgs ,
39+ NodeBatchRequestBody ,
40+ CreateEdgeArgs ,
41+ StorageApi ,
42+ BlobUploadRequestArgs ,
43+ } from './storage_api'
3344import { makeUrl } from './api_url'
3445
3546import { TNodeSliceIterator , GetNodesSliceFn } from './node_slice_iterator'
@@ -43,36 +54,11 @@ import moment from 'moment'
4354import { StatusCode } from './status_codes'
4455import { authCookie } from './auth/cookie'
4556import { makeEmptyNodeTextData , NodeUtil } from './typesutil'
57+ import { AuthenticationApi } from './authentication_api'
4658
4759const kHeaderCreatedAt = 'x-created-at'
4860const kHeaderLastModified = 'last-modified'
4961
50- /**
51- * Unique lookup keys that can match at most 1 node
52- */
53- export type UniqueNodeLookupKey =
54- /** Due to nid's nature there can be at most 1 node with a particular nid */
55- | { nid : string }
56- /** Unique because many nodes can refer to the same URL, but only one of them
57- * can be a bookmark */
58- | { webBookmark : { url : string } }
59-
60- export type NonUniqueNodeLookupKey =
61- /** Can match more than 1 node because multiple parts of a single web page
62- * can be quoted */
63- | { webQuote : { url : string } }
64- /** Can match more than 1 node because many nodes can refer to
65- * the same URL:
66- * - 0 or 1 can be @see NoteType.Url
67- * - AND at the same time more than 1 can be @see NodeType.WebQuote */
68- | { url : string }
69-
70- /**
71- * All the different types of keys that can be used to identify (during lookup,
72- * for example) one or more nodes.
73- */
74- export type NodeLookupKey = UniqueNodeLookupKey | NonUniqueNodeLookupKey
75-
7662export function isUniqueLookupKey (
7763 key : NodeLookupKey
7864) : key is UniqueNodeLookupKey {
@@ -82,18 +68,6 @@ export function isUniqueLookupKey(
8268 return false
8369}
8470
85- export type CreateNodeArgs = {
86- text : NodeTextData
87- from_nid ?: string [ ]
88- to_nid ?: string [ ]
89- index_text ?: NodeIndexText
90- extattrs ?: NodeExtattrs
91- ntype ?: NodeType
92- origin ?: OriginId
93- created_via ?: NodeCreatedVia
94- created_at ?: Date
95- }
96-
9771async function createNode (
9872 {
9973 text,
@@ -174,19 +148,13 @@ async function createOrUpdateNode(
174148 )
175149 }
176150
177- const updateArgs : UpdateNodeArgs = {
178- nid : existingNode . nid ,
151+ const patch : NodePatchRequest = {
179152 text : args . text ,
180153 index_text : args . index_text ,
181154 }
182155
183- const resp = await updateNode ( updateArgs , signal )
184- if ( ! resp . ok ) {
185- throw _makeResponseError ( resp , `Failed to update node ${ existingNode . nid } ` )
186- }
187- return {
188- nid : existingNode . nid ,
189- }
156+ await updateNode ( { nid : existingNode . nid , ...patch } , signal )
157+ return { nid : existingNode . nid }
190158}
191159
192160/**
@@ -247,10 +215,6 @@ function describeWhatWouldPreventNodeUpdate(args: CreateNodeArgs, node: TNode) {
247215 return `[what] - [attempted update arg] vs [existing node value]: ${ diff } `
248216}
249217
250- /**
251- * Lookup all the nodes that match a given key. For unique lookup keys either
252- * 0 or 1 nodes will be returned. For non-unique more than 1 node can be returned.
253- */
254218async function lookupNodes (
255219 key : UniqueNodeLookupKey ,
256220 signal ?: AbortSignal
@@ -314,10 +278,7 @@ async function lookupNodes(key: NodeLookupKey, signal?: AbortSignal) {
314278}
315279
316280async function uploadFiles (
317- files : File [ ] ,
318- from_nid : Optional < string > ,
319- to_nid : Optional < string > ,
320- createdVia : NodeCreatedVia ,
281+ { files, from_nid, to_nid, createdVia } : BlobUploadRequestArgs ,
321282 signal ?: AbortSignal
322283) : Promise < UploadMultipartResponse > {
323284 const query : UploadMultipartQuery = { created_via : createdVia }
@@ -358,7 +319,7 @@ async function buildFilesSearchIndex(
358319 return await resp . json ( )
359320}
360321
361- function mimeTypeIsSupportedByBuildIndex ( mimeType : MimeType ) {
322+ function mimeTypeIsSupportedByBuildIndex ( mimeType : MimeType ) : boolean {
362323 return Mime . isImage ( mimeType )
363324}
364325
@@ -445,12 +406,8 @@ async function getNode({
445406 return node
446407}
447408
448- type NodePatchRequestBody = {
449- nids : Nid [ ]
450- }
451-
452409async function getNodeBatch (
453- req : NodePatchRequestBody ,
410+ req : NodeBatchRequestBody ,
454411 signal ?: AbortSignal
455412) : Promise < NodeBatch > {
456413 const res = await fetch ( makeUrl ( `/node-batch-get` ) , {
@@ -468,14 +425,10 @@ async function getNodeBatch(
468425 }
469426}
470427
471- type UpdateNodeArgs = {
472- nid : string
473- text ?: NodeTextData
474- index_text ?: NodeIndexText
475- preserve_update_time ?: boolean
476- }
477-
478- async function updateNode ( args : UpdateNodeArgs , signal ?: AbortSignal ) {
428+ async function updateNode (
429+ args : { nid : string } & NodePatchRequest ,
430+ signal ?: AbortSignal
431+ ) : Promise < Ack > {
479432 const { nid, text, index_text, preserve_update_time } = args
480433 const headers = {
481434 'Content-type' : MimeType . JSON ,
@@ -485,12 +438,16 @@ async function updateNode(args: UpdateNodeArgs, signal?: AbortSignal) {
485438 index_text,
486439 preserve_update_time,
487440 }
488- return fetch ( makeUrl ( `/node/${ nid } ` ) , {
441+ const resp = await fetch ( makeUrl ( `/node/${ nid } ` ) , {
489442 method : 'PATCH' ,
490443 body : JSON . stringify ( request ) ,
491444 headers,
492445 signal,
493446 } )
447+ if ( resp . ok ) {
448+ return await resp . json ( )
449+ }
450+ throw _makeResponseError ( resp )
494451}
495452
496453async function getAuth ( {
@@ -508,7 +465,7 @@ async function getAuth({
508465 return await resp . json ( )
509466}
510467
511- export const getNodesSlice : GetNodesSliceFn = async ( {
468+ const getNodesSlice : GetNodesSliceFn = async ( {
512469 end_time,
513470 start_time,
514471 offset,
@@ -575,13 +532,7 @@ function _getNodesSliceIter({
575532 limit,
576533 origin,
577534 bucket_time_size,
578- } : {
579- end_time ?: number
580- start_time ?: number
581- limit ?: number
582- origin ?: OriginId
583- bucket_time_size ?: number
584- } ) {
535+ } : GetNodeSliceArgs ) {
585536 return new TNodeSliceIterator (
586537 getNodesSlice ,
587538 start_time ,
@@ -596,11 +547,7 @@ async function createEdge({
596547 from,
597548 to,
598549 signal,
599- } : {
600- from ?: string
601- to ?: string
602- signal : AbortSignal
603- } ) : Promise < TEdge > {
550+ } : CreateEdgeArgs ) : Promise < TEdge > {
604551 verifyIsNotNull ( from )
605552 verifyIsNotNull ( to )
606553 const req = {
@@ -644,14 +591,14 @@ async function getNodeAllEdges(
644591
645592async function switchEdgeStickiness ( {
646593 eid,
647- signal,
648594 on,
649595 off,
596+ signal,
650597} : {
651598 eid : string
652- signal : AbortSignal
653599 on : Optional < boolean >
654600 off : Optional < boolean >
601+ signal : AbortSignal
655602} ) : Promise < Ack > {
656603 verifyIsNotNull ( eid )
657604 const req = {
@@ -704,7 +651,7 @@ async function createSession(
704651 password : string ,
705652 permissions : number | null ,
706653 signal ?: AbortSignal
707- ) {
654+ ) : Promise < { } > {
708655 verifyIsNotNull ( email )
709656 verifyIsNotNull ( password )
710657 verifyIsNotNull ( signal )
@@ -909,7 +856,7 @@ async function passwordChange(
909856 old_password : string ,
910857 new_password : string ,
911858 signal ?: AbortSignal
912- ) {
859+ ) : Promise < Ack > {
913860 const value = { old_password, new_password }
914861 const resp = await fetch ( makeUrl ( '/auth/password-recover/change' ) , {
915862 method : 'POST' ,
@@ -1010,7 +957,7 @@ function _makeResponseError(response: Response, message?: string): Error {
1010957 } )
1011958}
1012959
1013- export const smuggler = {
960+ export const smuggler : StorageApi & AuthenticationApi = {
1014961 getAuth,
1015962 node : {
1016963 get : getNode ,
@@ -1035,16 +982,6 @@ export const smuggler = {
1035982 } ,
1036983 blob_index : {
1037984 build : buildFilesSearchIndex ,
1038- /** 'cfg' section is intended to expose properties of one of smuggler's
1039- * endpoints *without using network*. This information is unlikely to change
1040- * during application runtime which makes repeated network usage wasteful.
1041- *
1042- * It may be tempting to bake them into respective endpoint methods directly
1043- * (e.g. into 'blob_index.build'), but that is intentionally avoided to
1044- * keep a clearer boundary between raw REST endpoints and helper functionality.
1045- *
1046- * Similar sections may become useful for other endpoints
1047- */
1048985 cfg : {
1049986 supportsMime : mimeTypeIsSupportedByBuildIndex ,
1050987 } ,
0 commit comments