Skip to content

Commit 3a2271a

Browse files
committed
Node fetching code; README update
1 parent 49290bf commit 3a2271a

12 files changed

+3695
-45
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
**/api_token.txt
1+
**/api_token.txt
2+
.vscode

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@
22

33
> The man who is without qualification good at deliberating is the man who is capable of aiming in accordance with calculation at the best for man of things attainable by action.
44
5-
Eudaemon is a system of productivity tools intended primarily for my own use.
5+
**Eudaemon** is a highly opinionated system of productivity tools based on the framework of Aristotle's _Nicomachean Ethics_.
6+
7+
_Daemonist_ (δ) creates semi-responsive dashboards within [Dynalist](https://dynalist.io/) that pull data from the real world, surfacing information when it's relevant and moving it to logs when it isn't.
8+
9+
_Teleion_ (τ) provides an interactive view for reasoning about long-term goals and subgoals in terms of directed acyclic graphs.

daemonist/babel.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
presets: ["@babel/preset-env"]
3+
};

daemonist/package-lock.json

+3,569
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

daemonist/package.json

+9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,16 @@
2121
},
2222
"homepage": "https://github.com/tloen/eudaemon#readme",
2323
"dependencies": {
24+
"lodash": "^4.17.15",
2425
"node-fetch": "^2.6.0",
2526
"typescript": "^3.5.3"
27+
},
28+
"devDependencies": {
29+
"@babel/cli": "^7.5.5",
30+
"@babel/core": "^7.5.5",
31+
"@babel/node": "^7.5.5",
32+
"@babel/preset-env": "^7.5.5",
33+
"@types/lodash-es": "^4.17.3",
34+
"@types/node-fetch": "^2.5.0"
2635
}
2736
}

daemonist/src/api.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Dynalist } from "./dynalist";
22

33
export const ENDPOINTS = {
44
GET_FILES: "https://dynalist.io/api/v1/file/list",
5-
READ_DOCUMENT: "https://dynalist.io/api/v1/doc/read"
5+
GET_DOCUMENT: "https://dynalist.io/api/v1/doc/read"
66
};
77

88
type FailCode =
@@ -33,12 +33,22 @@ export interface GetFilesResponse extends SuccessfulResponse {
3333
files: Dynalist.File[];
3434
}
3535

36-
export interface DocumentReadResponse extends SuccessfulResponse {
37-
title: string;
38-
nodes: Dynalist.Node[];
36+
export interface DocumentReadNode {
37+
id: string;
38+
content: string;
39+
note: string;
40+
created: number;
41+
modified: number;
42+
children: string[];
43+
44+
checked?: boolean;
45+
checkbox?: boolean;
46+
color?: Dynalist.Color;
47+
heading?: Dynalist.HeadingLevel;
48+
collapsed?: boolean;
3949
}
4050

41-
export interface NodeKey {
42-
fileID: string;
43-
nodeID: string;
51+
export interface DocumentReadResponse extends SuccessfulResponse {
52+
title: string;
53+
nodes: DocumentReadNode[];
4454
}

daemonist/src/daemon.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { Dynalist } from "./dynalist";
2+
3+
const א = /[🏺😈👿🤖]/;
4+
const hasא = (node: Dynalist.Node) => !!א.exec(node.note);

daemonist/src/dynalist.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,18 @@ export namespace Dynalist {
3030
H3
3131
}
3232

33+
export interface NodeKey {
34+
documentId: string;
35+
nodeId: string;
36+
}
3337
export interface Node {
34-
id: string;
38+
key: NodeKey;
3539
content: string;
3640
note: string;
37-
created: number;
38-
modified: number;
39-
children: string[];
41+
created: Date;
42+
modified: Date;
4043

44+
children?: NodeKey[];
4145
checked?: boolean;
4246
checkbox?: boolean;
4347
color?: Color;

daemonist/src/index.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { DynalistAPI } from "./session";
22

3-
const api = new DynalistAPI("<|key|>");
3+
const api = new DynalistAPI(process.env.DYNALIST_API_TOKEN);
44

55
// api.getFileTree().then(console.log);
6-
api.readDocument("HP3Ov2goSBuIPEzMA2T3jRkk").then(console.log);
6+
// api.readDocument("HP3Ov2goSBuIPEzMA2T3jRkk").then(console.log);
7+
// api.getAllDocuments().then(console.log);
8+
api.getNodeForest().then(console.log);

daemonist/src/session.ts

+72-29
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import {
22
GetFilesResponse,
33
ENDPOINTS,
44
DocumentReadResponse,
5-
SuccessfulResponse
5+
SuccessfulResponse,
6+
DocumentReadNode
67
} from "./api";
78
import { Dynalist } from "./dynalist";
89
import fetch from "node-fetch";
@@ -14,46 +15,81 @@ interface FetchRequest {
1415

1516
export class DynalistAPI {
1617
private token: string;
17-
// private fileTree: Dynalist.File[] | undefined;
18-
// private cache; // TODO
18+
private cache: Cache;
1919

2020
constructor(token: string) {
2121
this.token = token;
2222
}
2323

24-
// Limit: 60 times per minute
25-
public async readAllDocuments(): Promise<Dynalist.Document[]> {
26-
return this.getFileTree()
27-
.then(
28-
(files): Promise<DocumentReadResponse[]> => {
29-
const requests = files.map(
30-
(file): FetchRequest => ({
31-
url: ENDPOINTS.READ_DOCUMENT,
32-
params: {
33-
file_id: file.id
34-
}
35-
})
36-
);
37-
return this.batchPostFetch<DocumentReadResponse>(requests, 1500);
38-
}
39-
)
40-
.then(responses =>
41-
responses.map(response => {
42-
return {
43-
id: "abc",
44-
title: response.title,
45-
nodes: response.nodes
46-
};
24+
public getNodeForest(): Promise<Dynalist.Node[]> {
25+
return this.getAllDocuments().then(files =>
26+
files.map(file => file.nodes).flat()
27+
);
28+
}
29+
30+
// Limit: 60 reads per minute
31+
public async getAllDocuments(): Promise<Dynalist.Document[]> {
32+
return this.getFileTree().then(files => {
33+
const documentFiles = files.filter(file => file.type === "document");
34+
35+
const requests = documentFiles.map(
36+
(file): FetchRequest => ({
37+
url: ENDPOINTS.GET_DOCUMENT,
38+
params: {
39+
file_id: file.id
40+
}
4741
})
4842
);
43+
return this.batchPostFetch<DocumentReadResponse>(requests, 1200).then(
44+
responses =>
45+
responses.map((response, i) => ({
46+
id: documentFiles[i].id,
47+
title: response.title,
48+
nodes: response.nodes.map(rawNode =>
49+
this.transformNode(rawNode, documentFiles[i].id)
50+
)
51+
}))
52+
);
53+
});
4954
}
5055

51-
public readDocument(documentId: string): Promise<Dynalist.Document> {
52-
return this.postFetch(ENDPOINTS.READ_DOCUMENT, {
56+
public getDocumentByTitle(title: string): Promise<Dynalist.Document> {
57+
return this.getFileTree().then(files => {
58+
const matchingFiles = files.filter(
59+
file => file.type === "document" && file.title == title
60+
);
61+
if (matchingFiles.length == 0) return undefined;
62+
else return this.getDocumentById(matchingFiles[0].id);
63+
});
64+
}
65+
66+
private transformNode(
67+
rawNode: DocumentReadNode,
68+
documentId: string
69+
): Dynalist.Node {
70+
return {
71+
...rawNode,
72+
key: {
73+
documentId,
74+
nodeId: rawNode.id
75+
},
76+
created: new Date(rawNode.created),
77+
modified: new Date(rawNode.modified),
78+
children: rawNode.children
79+
? rawNode.children.map(nodeId => ({
80+
documentId,
81+
nodeId
82+
}))
83+
: []
84+
};
85+
}
86+
87+
public getDocumentById(documentId: string): Promise<Dynalist.Document> {
88+
return this.postFetch(ENDPOINTS.GET_DOCUMENT, {
5389
file_id: documentId
5490
}).then((body: DocumentReadResponse) => ({
5591
id: documentId,
56-
nodes: body.nodes,
92+
nodes: body.nodes.map(rawNode => this.transformNode(rawNode, documentId)),
5793
title: body.title
5894
}));
5995
}
@@ -64,11 +100,17 @@ export class DynalistAPI {
64100
);
65101
}
66102

103+
// TODO: merge this into getting all docs
67104
private async batchPostFetch<T extends SuccessfulResponse>(
68105
requests: FetchRequest[],
69106
waitMilliseconds: number
70107
): Promise<T[]> {
71108
const results: T[] = [];
109+
console.log(
110+
`Got ${requests.length} requests with wait time ${waitMilliseconds /
111+
1000} seconds. Expect at least ${(requests.length * waitMilliseconds) /
112+
1000} seconds delay.`
113+
);
72114
for (const request of requests) {
73115
results.push(await this.postFetch<T>(request.url, request.params));
74116
await new Promise(_ => setTimeout(_, waitMilliseconds));
@@ -80,6 +122,7 @@ export class DynalistAPI {
80122
url: string,
81123
params?: any
82124
): Promise<T> {
125+
console.log(`POST ${url} with params ${JSON.stringify(params)}`);
83126
return fetch(url, {
84127
headers: {
85128
"Content-Type": "application/json"

daemonist/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"compilerOptions": {
3-
"lib": ["es2015", "es6", "dom"],
3+
"lib": ["es2015", "es6", "dom", "esnext"],
44
"outDir": "./build",
55
"target": "es5"
66
},

teleion/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is not here yet.

0 commit comments

Comments
 (0)