Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Commit 446e3ee

Browse files
author
Ray Arayilakath
committed
Push Experimental Blog and Database Classes to Public
1 parent e912a10 commit 446e3ee

File tree

6 files changed

+181
-45
lines changed

6 files changed

+181
-45
lines changed

index.js

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
import fs from 'fs';
22
import path from 'path';
3+
import _ from 'lodash';
34
import stringify from 'json-stable-stringify-without-jsonify';
45
import replapi from './src/source.js';
56

67
const defaultInitVariables = {
7-
username: undefined,
8+
username: '',
89
captcha: {
9-
token: undefined,
10+
token: '',
1011
},
1112
endpoints: {
12-
gql: undefined,
13-
restful: undefined,
14-
login: undefined,
13+
gql: '',
14+
restful: '',
15+
login: '',
1516
},
1617
markdown: {
17-
length: undefined,
18-
removeMarkdown: undefined,
18+
length: '',
19+
removeMarkdown: '',
1920
},
2021
previewCount: {
21-
comments: undefined,
22+
comments: '',
2223
},
23-
experimentalFeatures: undefined,
24+
experimentalFeatures: '',
25+
createDatabaseFlag: '',
2426
};
2527

2628
function sortByKey(a, b) {
@@ -29,28 +31,15 @@ function sortByKey(a, b) {
2931

3032
export default function ReplAPI(initVariables) {
3133
if (initVariables) {
32-
for (const [key, value] of Object.entries(initVariables)) {
33-
if (typeof value === 'object') {
34-
for (const [nestedKey, nestedValue] of Object.entries(value)) {
35-
if (typeof nestedValue !== 'string' && typeof nestedValue !== 'number') {
36-
throw new Error(`Invalid type for value of ${nestedKey}.`);
37-
} else if (defaultInitVariables[key][nestedKey] === undefined) {
38-
defaultInitVariables[key][nestedKey] = nestedValue;
39-
}
40-
}
41-
} else if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') {
42-
throw new Error(`Invalid type for value of ${key}.`);
43-
} else if (defaultInitVariables[key] === undefined) {
44-
defaultInitVariables[key] = value;
45-
}
46-
}
34+
_.assign(defaultInitVariables, initVariables)
4735
fs.writeFileSync(path.join(process.cwd(), '.replapirc.json'), `${stringify(defaultInitVariables, { cmp: sortByKey, space: 4 })}\n`, { encoding: 'utf8' });
4836
} else {
4937
fs.writeFileSync(path.join(process.cwd(), '.replapirc.json'), `${stringify(defaultInitVariables, { cmp: sortByKey, space: 4 })}\n`, { encoding: 'utf8' });
5038
}
5139

5240
return {
5341
defaults: defaultInitVariables,
42+
Blog: replapi.Blog,
5443
Board: replapi.Board,
5544
Comment: replapi.Comment,
5645
CustomDataQuery: replapi.CustomDataQuery,

package-lock.json

Lines changed: 38 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@
2828
"dependencies": {
2929
"atob": "^2.1.2",
3030
"json-stable-stringify-without-jsonify": "^1.0.1",
31+
"lodash": "^4.17.21",
3132
"node-fetch": "^2.6.1",
32-
"node-html-parser": "^3.1.3"
33+
"node-html-parser": "^3.1.3",
34+
"rss-parser": "^3.12.0"
3335
},
3436
"devDependencies": {
37+
"@replit/database": "^2.0.1",
3538
"eslint": "^7.24.0",
3639
"eslint-config-airbnb-base": "^14.2.1",
3740
"eslint-plugin-import": "^2.22.1"

src/classes/Blog.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import Parser from 'rss-parser';
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
const parser = new Parser();
6+
7+
let exportable;
8+
let isExperimentalFeaturesEnabled;
9+
if (fs.existsSync(path.join(process.cwd(), '.replapirc.json'))) {
10+
isExperimentalFeaturesEnabled = JSON.parse(fs.readFileSync(path.join(process.cwd(), '.replapirc.json'))).experimentalFeatures;
11+
}
12+
13+
if (isExperimentalFeaturesEnabled) {
14+
exportable = class Blog {
15+
async blogData() {
16+
const feed = await parser.parseURL('https://blog.replit.com/feed.xml');
17+
delete feed.items;
18+
19+
return feed;
20+
}
21+
22+
async blogItems(order = 'newest', count = 10) {
23+
const feed = await parser.parseURL('https://blog.replit.com/feed.xml');
24+
25+
if (order === 'oldest') feed.items.reverse();
26+
const posts = feed.items.slice(0, count);
27+
28+
return posts;
29+
}
30+
};
31+
} else {
32+
exportable = function noExperimentalFeatures() {
33+
console.log('Experimental Features are not enabled. To learn more about experimental features please visit the documentation.');
34+
};
35+
}
36+
37+
export default exportable;

src/classes/Database.js

Lines changed: 87 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import fetch from 'node-fetch';
2+
import _ from 'lodash';
23
import fs from 'fs';
34
import path from 'path';
4-
5-
import headers from '../utils/headers.js';
6-
import constants from '../utils/constants.js';
5+
import crypto from 'crypto';
76

87
function hash(value, salt) {
98
const hashItem = crypto.createHmac('sha512', salt);
@@ -31,36 +30,106 @@ if (fs.existsSync(path.join(process.cwd(), '.replapirc.json'))) {
3130

3231
if (isExperimentalFeaturesEnabled) {
3332
exportable = class Database {
34-
constructor(replitdbtoken, salt, options) {
35-
this.replitdbtoken = replitdbtoken || process.env.REPLIT_DB_URL.split('/')[4];
33+
constructor(dbToken, salt = '', options = {}) {
34+
if (!process.env.REPLIT_DB_URL) throw new Error('Please run the Database Class on a Replit Project only.');
35+
36+
this.dbToken = dbToken || process.env.REPLIT_DB_URL;
3637
this.salt = salt;
37-
this.options = options;
38+
this.options = {
39+
id: String(dbToken).split('/')[4] || process.env.REPLIT_DB_URL.split('/')[4],
40+
owner: process.env.REPL_OWNER,
41+
collaborators: { ...options.collaborators },
42+
password: { ...hash(String(options.password), String(salt)) },
43+
type: options.type,
44+
encrypted: options.encrypted || [false],
45+
'max-items': options['max-items'] || 10,
46+
};
47+
}
48+
49+
async init() {
50+
const isDatabaseSetup = await fetch(`${this.dbToken}/${encodeURIComponent('replapi_database_config')}`, {
51+
method: 'GET',
52+
}).then((res) => res.text());
53+
54+
if (!isDatabaseSetup) {
55+
if (this.options.type === 'plus') {
56+
let createDatabaseFlag;
57+
if (fs.existsSync(path.join(process.cwd(), '.replapirc.json'))) {
58+
createDatabaseFlag = JSON.parse(fs.readFileSync(path.join(process.cwd(), '.replapirc.json'))).createDatabaseFlag;
59+
}
60+
61+
if (createDatabaseFlag) {
62+
const info = await fetch(`${this.dbToken}`, {
63+
method: 'POST',
64+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
65+
body: `${encodeURIComponent('replapi_database_config')}=${encodeURIComponent(JSON.stringify({ ...this.options }))}`,
66+
});
67+
} else {
68+
throw new Error('Are you sure you want to use these options to configure a Database? You will not be able to change these options in the future. If you are, then in your .replapirc.json file set a "createDatabaseFlag" key to "true". For more information, read the documentation.');
69+
}
70+
} else if (this.options.type === 'repldb') {
71+
const info = await fetch(`${this.dbToken}`, {
72+
method: 'POST',
73+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
74+
body: `${encodeURIComponent('replapi_database_config')}=${encodeURIComponent(JSON.stringify({ ...this.options }))}`,
75+
});
76+
} else {
77+
throw new Error('Invalid Database Type. For a normal database, use the "repldb" option.');
78+
}
79+
}
3880
}
3981

40-
async set(key, value) {
41-
const info = await fetch(`https://kv.replit.com/v0/${this.replitdbtoken}`, {
82+
async createCollection(collectionName) {
83+
const info = await fetch(`${this.dbToken}`, {
4284
method: 'POST',
43-
headers,
44-
body: `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(value))}`,
85+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
86+
body: `${encodeURIComponent(collectionName)}=${encodeURIComponent(JSON.stringify({}))}`,
87+
});
88+
}
89+
90+
async createDoc(collectionName, docName, docItems) {
91+
const collection = await this.getCollection(collectionName);
92+
collection[docName] = { ...docItems };
93+
94+
const info = await fetch(`${this.dbToken}`, {
95+
method: 'POST',
96+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
97+
body: `${encodeURIComponent(collectionName)}=${encodeURIComponent(JSON.stringify(collection))}`,
98+
});
99+
}
100+
101+
async getCollection(collectionName) {
102+
const info = await fetch(`${this.dbToken}/${collectionName}`, {
103+
method: 'GET',
45104
}).then((res) => res.json());
105+
106+
return info;
46107
}
47108

48-
async get(key) {
49-
const info = await fetch(`https://kv.replit.com/v0/${this.replitdbtoken}/${key}`, {
109+
async getDoc(collectionName, docName) {
110+
const info = await fetch(`${this.dbToken}/${collectionName}`, {
50111
method: 'GET',
51-
headers,
52-
}).then((res) => {
53-
res.json();
112+
}).then((res) => res.json());
113+
114+
return info[docName];
115+
}
116+
117+
async updateDoc(collectionName, docName, docItems) {
118+
const collection = await this.getCollection(collectionName);
119+
_.assignIn(collection[docName], docItems);
120+
121+
const info = await fetch(`${this.dbToken}`, {
122+
method: 'POST',
123+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
124+
body: `${encodeURIComponent(collectionName)}=${encodeURIComponent(JSON.stringify(collection))}`,
54125
});
55126
}
56127

57128
async delete(key) {
58129
const info = await fetch(`https://kv.replit.com/v0/${this.replitdbtoken}/${key}`, {
59130
method: 'GET',
60131
headers,
61-
}).then((res) => {
62-
res.json();
63-
});
132+
}).then((res) => res.json() );
64133
}
65134
};
66135
} else {

src/source.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Blog from './classes/Blog.js';
12
import Board from './classes/Board.js';
23
import Comment from './classes/Comment.js';
34
import { CustomDataQuery, CustomRecursiveQuery } from './classes/Custom.js';
@@ -11,6 +12,7 @@ import Repl from './classes/Repl.js';
1112
import User from './classes/User.js';
1213

1314
export default {
15+
Blog,
1416
Board,
1517
Comment,
1618
CustomDataQuery,

0 commit comments

Comments
 (0)