joplin-plugin-backup 0.5.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ENV +1 -0
- package/.husky/pre-commit +4 -0
- package/.husky/pre-push +4 -0
- package/.prettierignore +4 -0
- package/.prettierrc.json +16 -0
- package/.vscode/settings.json +4 -0
- package/README.md +90 -84
- package/__test__/backup.test.ts +838 -0
- package/__test__/help.test.ts +74 -0
- package/__test__/pw.test.ts +82 -0
- package/__test__/sevenZip.test.ts +102 -0
- package/__test__/sevenZipUpdateBinPath.test.ts +16 -0
- package/img/main.jpg +0 -0
- package/package.json +71 -33
- package/plugin.config.json +3 -3
- package/publish/io.github.jackgruber.backup.jpl +0 -0
- package/publish/io.github.jackgruber.backup.json +8 -5
- package/CHANGELOG.md +0 -54
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { helper } from "../src/helper";
|
|
2
|
+
|
|
3
|
+
describe("Test helper", function () {
|
|
4
|
+
it(`validFileName`, async () => {
|
|
5
|
+
const testCases = [
|
|
6
|
+
{
|
|
7
|
+
fileName: "some test file.txt",
|
|
8
|
+
expected: true,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
fileName: "some ^test file.txt",
|
|
12
|
+
expected: true,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
fileName: "some :test file.txt",
|
|
16
|
+
expected: false,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
fileName: "some \\test file.txt",
|
|
20
|
+
expected: false,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
fileName: "some |test file.txt",
|
|
24
|
+
expected: false,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
fileName: "some /test file.txt",
|
|
28
|
+
expected: false,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
fileName: "some *test file.txt",
|
|
32
|
+
expected: false,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
fileName: "some ?test file.txt",
|
|
36
|
+
expected: false,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
fileName: "some <test file.txt",
|
|
40
|
+
expected: false,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
fileName: "some >test file.txt",
|
|
44
|
+
expected: false,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
fileName: "com9.txt",
|
|
48
|
+
expected: false,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
fileName: "nul.txt",
|
|
52
|
+
expected: false,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
fileName: "prn.txt",
|
|
56
|
+
expected: false,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
fileName: "con.txt",
|
|
60
|
+
expected: false,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
fileName: "lpt5.txt",
|
|
64
|
+
expected: false,
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
for (const testCase of testCases) {
|
|
69
|
+
expect(await helper.validFileName(testCase.fileName)).toBe(
|
|
70
|
+
testCase.expected
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Backup } from "../src/Backup";
|
|
2
|
+
import joplin from "api";
|
|
3
|
+
import { when } from "jest-when";
|
|
4
|
+
|
|
5
|
+
let backup = null;
|
|
6
|
+
|
|
7
|
+
describe("Password", function () {
|
|
8
|
+
beforeEach(async () => {
|
|
9
|
+
backup = new Backup() as any;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it(`Check`, async () => {
|
|
13
|
+
const spyOnsSettingsValue = jest.spyOn(joplin.settings, "value");
|
|
14
|
+
const spyOnsSettingsSetValue = jest.spyOn(joplin.settings, "setValue");
|
|
15
|
+
|
|
16
|
+
const testCases = [
|
|
17
|
+
{
|
|
18
|
+
usePassword: false,
|
|
19
|
+
password: "",
|
|
20
|
+
passwordRepeat: "",
|
|
21
|
+
expected: 0,
|
|
22
|
+
called: 2,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
usePassword: false,
|
|
26
|
+
password: "test",
|
|
27
|
+
passwordRepeat: "test",
|
|
28
|
+
expected: 0,
|
|
29
|
+
called: 2,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
usePassword: false,
|
|
33
|
+
password: "testA",
|
|
34
|
+
passwordRepeat: "testB",
|
|
35
|
+
expected: 0,
|
|
36
|
+
called: 2,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
usePassword: true,
|
|
40
|
+
password: "test",
|
|
41
|
+
passwordRepeat: "test",
|
|
42
|
+
expected: 1,
|
|
43
|
+
called: 0,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
usePassword: true,
|
|
47
|
+
password: "testA",
|
|
48
|
+
passwordRepeat: "testB",
|
|
49
|
+
expected: -1,
|
|
50
|
+
called: 2,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
usePassword: true,
|
|
54
|
+
password: " ",
|
|
55
|
+
passwordRepeat: " ",
|
|
56
|
+
expected: -1,
|
|
57
|
+
called: 2,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
usePassword: true,
|
|
61
|
+
password: "",
|
|
62
|
+
passwordRepeat: " ",
|
|
63
|
+
expected: -1,
|
|
64
|
+
called: 2,
|
|
65
|
+
},
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
for (const testCase of testCases) {
|
|
69
|
+
/* prettier-ignore */
|
|
70
|
+
when(spyOnsSettingsValue)
|
|
71
|
+
.mockImplementation(() => Promise.resolve("no mockImplementation"))
|
|
72
|
+
.calledWith("usePassword").mockImplementation(() => Promise.resolve(testCase.usePassword))
|
|
73
|
+
.calledWith("password").mockImplementation(() => Promise.resolve(testCase.password))
|
|
74
|
+
.calledWith("passwordRepeat").mockImplementation(() => Promise.resolve(testCase.passwordRepeat));
|
|
75
|
+
expect(await backup.checkPassword()).toBe(testCase.expected);
|
|
76
|
+
|
|
77
|
+
await backup.enablePassword();
|
|
78
|
+
expect(spyOnsSettingsSetValue).toBeCalledTimes(testCase.called);
|
|
79
|
+
spyOnsSettingsSetValue.mockReset();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { sevenZip } from "../src/sevenZip";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as fs from "fs-extra";
|
|
4
|
+
|
|
5
|
+
const testBaseDir = path.join(__dirname, "ziptests");
|
|
6
|
+
|
|
7
|
+
describe("Test sevenZip", function () {
|
|
8
|
+
beforeAll(async () => {});
|
|
9
|
+
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
fs.emptyDirSync(testBaseDir);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterAll(async () => {
|
|
15
|
+
fs.removeSync(testBaseDir);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it(`List`, async () => {
|
|
19
|
+
const file1Name = "file1.txt";
|
|
20
|
+
const file2Name = "file2.txt";
|
|
21
|
+
const file3Name = "file3.txt";
|
|
22
|
+
const file1 = path.join(testBaseDir, file1Name);
|
|
23
|
+
fs.emptyDirSync(path.join(testBaseDir, "sub"));
|
|
24
|
+
const file2 = path.join(testBaseDir, "sub", file2Name);
|
|
25
|
+
const file3 = path.join(testBaseDir, file3Name);
|
|
26
|
+
const zip = path.join(testBaseDir, "file.7z");
|
|
27
|
+
fs.writeFileSync(file1, "file");
|
|
28
|
+
fs.writeFileSync(file2, "file");
|
|
29
|
+
fs.writeFileSync(file3, "file");
|
|
30
|
+
expect(fs.existsSync(file1)).toBe(true);
|
|
31
|
+
expect(fs.existsSync(file2)).toBe(true);
|
|
32
|
+
expect(fs.existsSync(file3)).toBe(true);
|
|
33
|
+
expect(fs.existsSync(zip)).toBe(false);
|
|
34
|
+
|
|
35
|
+
expect(await sevenZip.add(zip, testBaseDir + "\\*", "secret")).toBe(true);
|
|
36
|
+
expect(fs.existsSync(zip)).toBe(true);
|
|
37
|
+
|
|
38
|
+
expect(await sevenZip.passwordProtected(zip)).toBe(true);
|
|
39
|
+
|
|
40
|
+
const fileList = await sevenZip.list(zip, "secret");
|
|
41
|
+
expect(fileList.length).toBe(4);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it(`passwordProtected`, async () => {
|
|
45
|
+
const fileName = "file.txt";
|
|
46
|
+
const file = path.join(testBaseDir, fileName);
|
|
47
|
+
const zipNoPw = path.join(testBaseDir, "nowpw.7z");
|
|
48
|
+
const zippw = path.join(testBaseDir, "pw.7z");
|
|
49
|
+
|
|
50
|
+
fs.writeFileSync(file, "file");
|
|
51
|
+
expect(fs.existsSync(file)).toBe(true);
|
|
52
|
+
|
|
53
|
+
expect(fs.existsSync(zipNoPw)).toBe(false);
|
|
54
|
+
expect(await sevenZip.add(zipNoPw, file)).toBe(true);
|
|
55
|
+
expect(fs.existsSync(zipNoPw)).toBe(true);
|
|
56
|
+
expect(await sevenZip.passwordProtected(zipNoPw)).toBe(false);
|
|
57
|
+
|
|
58
|
+
expect(fs.existsSync(zippw)).toBe(false);
|
|
59
|
+
expect(await sevenZip.add(zippw, file, "secret")).toBe(true);
|
|
60
|
+
expect(fs.existsSync(zippw)).toBe(true);
|
|
61
|
+
expect(await sevenZip.passwordProtected(zippw)).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("Add", function () {
|
|
65
|
+
it(`File`, async () => {
|
|
66
|
+
const fileName = "file.txt";
|
|
67
|
+
const file = path.join(testBaseDir, fileName);
|
|
68
|
+
const zip = path.join(testBaseDir, "file.7z");
|
|
69
|
+
fs.writeFileSync(file, "file");
|
|
70
|
+
expect(fs.existsSync(file)).toBe(true);
|
|
71
|
+
expect(fs.existsSync(zip)).toBe(false);
|
|
72
|
+
|
|
73
|
+
const result = await sevenZip.add(zip, file);
|
|
74
|
+
expect(result).toBe(true);
|
|
75
|
+
expect(fs.existsSync(zip)).toBe(true);
|
|
76
|
+
|
|
77
|
+
const sevenZipList = await sevenZip.list(zip);
|
|
78
|
+
expect(sevenZipList.length).toBe(1);
|
|
79
|
+
expect(sevenZipList[0].file).toBe(fileName);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it(`File with password`, async () => {
|
|
83
|
+
const fileName = "file.txt";
|
|
84
|
+
const file = path.join(testBaseDir, fileName);
|
|
85
|
+
const zip = path.join(testBaseDir, "file.7z");
|
|
86
|
+
const password = "secret";
|
|
87
|
+
fs.writeFileSync(file, "file");
|
|
88
|
+
expect(fs.existsSync(file)).toBe(true);
|
|
89
|
+
expect(fs.existsSync(zip)).toBe(false);
|
|
90
|
+
|
|
91
|
+
const result = await sevenZip.add(zip, file, password);
|
|
92
|
+
expect(result).toBe(true);
|
|
93
|
+
expect(fs.existsSync(zip)).toBe(true);
|
|
94
|
+
|
|
95
|
+
expect(await sevenZip.passwordProtected(zip)).toBe(true);
|
|
96
|
+
|
|
97
|
+
const sevenZipList = await sevenZip.list(zip, password);
|
|
98
|
+
expect(sevenZipList.length).toBe(1);
|
|
99
|
+
expect(sevenZipList[0].file).toBe(fileName);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { sevenZip, pathTo7zip } from "../src/sevenZip";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import joplin from "api";
|
|
4
|
+
|
|
5
|
+
it(`Set bin from joplin`, async () => {
|
|
6
|
+
const pathBevor = pathTo7zip;
|
|
7
|
+
const pathAdd = "addJoplinPath";
|
|
8
|
+
const pathAfter = path.join(pathAdd, "7zip-bin", pathTo7zip);
|
|
9
|
+
|
|
10
|
+
jest.spyOn(joplin.plugins, "installationDir").mockImplementation(async () => {
|
|
11
|
+
return pathAdd;
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
await sevenZip.updateBinPath();
|
|
15
|
+
expect(pathTo7zip).toBe(pathAfter);
|
|
16
|
+
});
|
package/img/main.jpg
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,33 +1,71 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "joplin-plugin-backup",
|
|
3
|
-
"version": "0.5
|
|
4
|
-
"scripts": {
|
|
5
|
-
"dist": "webpack --joplin-plugin-config buildMain && webpack --joplin-plugin-config buildExtraScripts && webpack --joplin-plugin-config createArchive",
|
|
6
|
-
"prepare": "npm run dist",
|
|
7
|
-
"update": "npm install -g generator-joplin && yo joplin --update"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"webpack": "^
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "joplin-plugin-backup",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"dist": "webpack --joplin-plugin-config buildMain && webpack --joplin-plugin-config buildExtraScripts && webpack --joplin-plugin-config createArchive",
|
|
6
|
+
"prepare": "npm run dist && husky install",
|
|
7
|
+
"update": "npm install -g generator-joplin && yo joplin --update",
|
|
8
|
+
"release": "npm test && node ./node_modules/joplinplugindevtools/dist/createRelease.js",
|
|
9
|
+
"preRelease": "npm test && node ./node_modules/joplinplugindevtools/dist/createRelease.js --prerelease",
|
|
10
|
+
"gitRelease": "node ./node_modules/joplinplugindevtools/dist/createRelease.js --upload",
|
|
11
|
+
"gitPreRelease": "node ./node_modules/joplinplugindevtools/dist/createRelease.js --upload --prerelease",
|
|
12
|
+
"test": "jest"
|
|
13
|
+
},
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"joplin-plugin"
|
|
17
|
+
],
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/jest": "^26.0.23",
|
|
20
|
+
"@types/node": "^14.0.14",
|
|
21
|
+
"axios": "^0.21.1",
|
|
22
|
+
"chalk": "^4.1.0",
|
|
23
|
+
"copy-webpack-plugin": "^6.1.0",
|
|
24
|
+
"dotenv": "^10.0.0",
|
|
25
|
+
"fs-extra": "^9.0.1",
|
|
26
|
+
"glob": "^7.1.6",
|
|
27
|
+
"husky": "^6.0.0",
|
|
28
|
+
"jest": "^27.0.4",
|
|
29
|
+
"jest-when": "^3.3.1",
|
|
30
|
+
"joplinplugindevtools": "^1.0.14",
|
|
31
|
+
"lint-staged": "^11.0.0",
|
|
32
|
+
"mime": "^2.5.2",
|
|
33
|
+
"on-build-webpack": "^0.1.0",
|
|
34
|
+
"prettier": "2.3.0",
|
|
35
|
+
"tar": "^6.0.5",
|
|
36
|
+
"ts-jest": "^27.0.2",
|
|
37
|
+
"ts-loader": "^7.0.5",
|
|
38
|
+
"typescript": "^3.9.3",
|
|
39
|
+
"webpack": "^4.43.0",
|
|
40
|
+
"webpack-cli": "^3.3.11",
|
|
41
|
+
"yargs": "^16.2.0"
|
|
42
|
+
},
|
|
43
|
+
"browser": {
|
|
44
|
+
"fs": false,
|
|
45
|
+
"child_process": false
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"7zip-bin": "^5.1.1",
|
|
49
|
+
"electron-log": "^4.3.1",
|
|
50
|
+
"moment": "^2.29.1",
|
|
51
|
+
"node-7z": "^2.1.2"
|
|
52
|
+
},
|
|
53
|
+
"lint-staged": {
|
|
54
|
+
"**/*": "prettier --write --ignore-unknown"
|
|
55
|
+
},
|
|
56
|
+
"jest": {
|
|
57
|
+
"transform": {
|
|
58
|
+
".(ts|tsx)": "ts-jest"
|
|
59
|
+
},
|
|
60
|
+
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
|
|
61
|
+
"moduleFileExtensions": [
|
|
62
|
+
"ts",
|
|
63
|
+
"tsx",
|
|
64
|
+
"js"
|
|
65
|
+
],
|
|
66
|
+
"moduleNameMapper": {
|
|
67
|
+
"^api$": "<rootDir>/node_modules/joplinplugindevtools/dist/apiMock.js",
|
|
68
|
+
"^api/types$": "<rootDir>/api/types"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
package/plugin.config.json
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"extraScripts": []
|
|
3
|
+
}
|
|
Binary file
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"id": "io.github.jackgruber.backup",
|
|
4
|
-
"app_min_version": "1.
|
|
5
|
-
"version": "0.5
|
|
4
|
+
"app_min_version": "2.1.3",
|
|
5
|
+
"version": "1.0.5",
|
|
6
6
|
"name": "Simple Backup",
|
|
7
7
|
"description": "Plugin to create manual and automatic backups.",
|
|
8
8
|
"author": "JackGruber",
|
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
"keywords": [
|
|
12
12
|
"backup",
|
|
13
13
|
"jex",
|
|
14
|
-
"export"
|
|
14
|
+
"export",
|
|
15
|
+
"zip",
|
|
16
|
+
"7zip",
|
|
17
|
+
"encrypted"
|
|
15
18
|
],
|
|
16
|
-
"_publish_hash": "sha256:
|
|
17
|
-
"_publish_commit": "master:
|
|
19
|
+
"_publish_hash": "sha256:afa40d7e0ed66a962aab6cbb7a01401cced7e165c4eddec4f1bbbe13ea96187e",
|
|
20
|
+
"_publish_commit": "master:2c035a3d426785deeaacc1948a2469d0824e0c25"
|
|
18
21
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## v0.5.3 (2021-04-03)
|
|
4
|
-
|
|
5
|
-
- Add: Backup settings.json
|
|
6
|
-
- Optimize: #7 Better error message when a backup is created twice in a row in the same minute
|
|
7
|
-
|
|
8
|
-
## v0.5.2 (2021-02-13)
|
|
9
|
-
|
|
10
|
-
- Only internal changes
|
|
11
|
-
|
|
12
|
-
## v0.5.1 (2021-02-07)
|
|
13
|
-
|
|
14
|
-
- Fix: Incomplete backup.log with only one backup set
|
|
15
|
-
|
|
16
|
-
## v0.5.0 (2021-02-07)
|
|
17
|
-
|
|
18
|
-
- Add: Option for Backuplogfile
|
|
19
|
-
- Add: Option to create a backup only if something has changed #3
|
|
20
|
-
|
|
21
|
-
## v0.4.1 (2021-01-23)
|
|
22
|
-
|
|
23
|
-
- Optimize: Store profile data in `profile` folder
|
|
24
|
-
|
|
25
|
-
## v0.4.0 (2021-01-21)
|
|
26
|
-
|
|
27
|
-
- Add `templates` to backup
|
|
28
|
-
- Optimize: Delete old backups at the end of the backup job
|
|
29
|
-
|
|
30
|
-
## v0.3.1 (2021-01-21)
|
|
31
|
-
|
|
32
|
-
- Fix #1: Unsupported characters in filename
|
|
33
|
-
|
|
34
|
-
## v0.3.0 (2021-01-17)
|
|
35
|
-
|
|
36
|
-
- Fix: Backup not only the last 50 notebooks
|
|
37
|
-
- Add: Backup userchrome.css and userstyle.css
|
|
38
|
-
- Add: Option to create single file JEX for all notebooks
|
|
39
|
-
|
|
40
|
-
## v0.2.2 (2021-01-17)
|
|
41
|
-
|
|
42
|
-
- Fix: Check if keymap-desktop.json exists
|
|
43
|
-
|
|
44
|
-
## v0.2.1 (2021-01-16)
|
|
45
|
-
|
|
46
|
-
- remove seconds from folder
|
|
47
|
-
|
|
48
|
-
## v0.2.0 (2021-01-14)
|
|
49
|
-
|
|
50
|
-
- Add: Automatic backups every X hours
|
|
51
|
-
|
|
52
|
-
## v0.1.0 (2021-01-14)
|
|
53
|
-
|
|
54
|
-
- First version
|