simple-github-gist-api 2.0.3 → 2.0.7

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Vighnesh Raut
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,63 +1,20 @@
1
1
  # Simple Github Gist API
2
2
 
3
- <p>
4
- <img alt="npm" src="https://img.shields.io/npm/dt/simple-github-gist-api">
5
- <img alt="npm" src="https://img.shields.io/npm/v/simple-github-gist-api">
6
- </p>
7
-
8
- > This documentation is for v2 of the lib. v2 has a few breaking changes.
9
- >
10
- > You can find the v1 documentation in the `docs` directory (On Github).
3
+ [![npm (scoped)](https://img.shields.io/npm/v/simple-github-gist-api)](https://www.npmjs.com/package/simple-github-gist-api)
4
+ [![npm bundle size (scoped)](https://img.shields.io/bundlephobia/minzip/simple-github-gist-api)](https://img.shields.io/bundlephobia/minzip/simple-github-gist-api)
5
+ [![npm](https://img.shields.io/npm/dt/simple-github-gist-api)](https://img.shields.io/npm/dt/simple-github-gist-api)
6
+ [![GitHub](https://img.shields.io/github/license/vighnesh153/simple-github-gist-api)](https://github.com/vighnesh153/simple-github-gist-api/blob/master/LICENSE)
7
+ [![GitHub issues](https://img.shields.io/github/issues/vighnesh153/simple-github-gist-api)](https://github.com/vighnesh153/simple-github-gist-api/issues)
11
8
 
12
9
  Use this promise based API to
13
10
  store data on your github gists without the
14
11
  need to make those tedious HTTP requests.
15
12
 
16
- > Note: Github Gist's API work on commit-id basis. If you save anything,
17
- > it is a new commit and the commit-id changes. So, when you save,
18
- > don't do that simultaneously.
19
- >
20
- > For instance, assume you are using this in your API.
21
- > And you have an endpoint `/create-file`.
22
- >
23
- > Think multiple people making request at the same time:
24
- ```
25
- /create-file?name=1.json
26
- /create-file?name=2.json
27
- /create-file?name=3.json
28
- ...
29
- ```
30
-
31
- > If this happens at the same time, then we cannot guarantee that the
32
- > all the files will be saved. Maybe when creating both 2.json and 3.json,
33
- > we are making use of the same commit-id. Both will work but 1 will over-write
34
- > the other commit.
35
- >
36
- > But if you do:
37
-
38
- ```ts
39
- const file1 = gist.createFile('1.json', "{}")
40
- const file2 = gist.createFile('2.json', "{}")
41
- const file3 = gist.createFile('3.json', "{}")
42
-
43
- await file1.save();
44
- await file2.save();
45
- await file3.save();
46
- ```
47
- >
48
- > this will work as the latest commit-id will be fetched when
49
- > saving the next file.
50
- >
51
- > Or
52
- ```ts
53
- gist.save();
54
- ```
55
- > this will work as well because all the changes will go in a single commit.
56
-
13
+ > Note: This documentation is for v2 of the lib. v2 has a few breaking changes. You can find the v1 documentation in the `docs` directory (On Github).
57
14
 
58
15
  ## Installation
59
16
 
60
- ```
17
+ ```sh
61
18
  npm i -S simple-github-gist-api
62
19
  ```
63
20
 
@@ -172,6 +129,42 @@ await gist.save();
172
129
  ```
173
130
  > Only files that have un-saved changes will be saved.
174
131
 
132
+ ### Gotchas
133
+
134
+ Github Gist's API work on commit-id basis. If you save anything,
135
+ it is a new commit and the commit-id changes. So, when you save,
136
+ don't do that simultaneously.
137
+
138
+ For instance, assume you have an endpoint `/create-file`. And if multiple people making request at the same time:
139
+ ```
140
+ /create-file?name=1.json
141
+ /create-file?name=2.json
142
+ /create-file?name=3.json
143
+ ...
144
+ ```
145
+
146
+ then we cannot guarantee that the
147
+ all the files will be saved. When creating `2.json` and `3.json`, there is a possibility
148
+ that we make use of the same commit-id at HEAD. Both will work but 1 will over-write
149
+ the other commit.
150
+
151
+ But if you do the following, it will work as the latest commit-id will be fetched when
152
+ saving each file.
153
+ ```ts
154
+ const file1 = gist.createFile('1.json', "{}")
155
+ const file2 = gist.createFile('2.json', "{}")
156
+ const file3 = gist.createFile('3.json', "{}")
157
+
158
+ await file1.save();
159
+ await file2.save();
160
+ await file3.save();
161
+ ```
162
+
163
+ Or even this will work as well because all the changes will be pushed in a single commit.
164
+ ```ts
165
+ gist.save();
166
+ ```
167
+
175
168
  ### Sample
176
169
  ```ts
177
170
  import GithubGist from "./src";
package/dist/index.d.ts CHANGED
@@ -1,27 +1,2 @@
1
- import File from './models/file';
2
- import GistAuthConfig from './models/gist-auth-config';
3
- export declare const getHelloWorldString: () => string;
4
- export declare class GithubGistApi {
5
- private personalAccessToken;
6
- private _pureGistIdentifierName;
7
- static __getHelloWorldString: () => string;
8
- private readonly _gistIdentifierName;
9
- private _gistId;
10
- private _username;
11
- private _files;
12
- get gistId(): string;
13
- get username(): string;
14
- isPublic: boolean;
15
- allowCors: boolean;
16
- constructor(personalAccessToken?: string, _pureGistIdentifierName?: string);
17
- touch(): Promise<void>;
18
- createFile(name: string, initialContent: string): void;
19
- getFile(name: string): File;
20
- getFileNames(): string[];
21
- save(): Promise<void>;
22
- private _fetchGistIfExists;
23
- private _createGistForFirstTime;
24
- _getLatestCommit(): Promise<string>;
25
- private _selfInitialize;
26
- _authConfig(): GistAuthConfig;
27
- }
1
+ import GithubGist from "./models/GithubGist";
2
+ export default GithubGist;
package/dist/index.js CHANGED
@@ -1,173 +1,4 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.GithubGistApi = exports.getHelloWorldString = void 0;
13
- const file_1 = require("./models/file");
14
- const argument_not_specified_1 = require("./util/argument-not-specified");
15
- const formatted_gist_identifier_1 = require("./util/formatted-gist-identifier");
16
- const is_string_empty_1 = require("./util/is-string-empty");
17
- const token_validity_1 = require("./token-validity");
18
- const constants_1 = require("./constants");
19
- const axios_1 = require("axios");
20
- const getHelloWorldString = () => {
21
- return 'Hello World!';
22
- };
23
- exports.getHelloWorldString = getHelloWorldString;
24
- class GithubGistApi {
25
- constructor(personalAccessToken = (0, argument_not_specified_1.default)('personalAccessToken'), _pureGistIdentifierName = (0, argument_not_specified_1.default)('gistIdentifierName')) {
26
- this.personalAccessToken = personalAccessToken;
27
- this._pureGistIdentifierName = _pureGistIdentifierName;
28
- this._gistId = '';
29
- this._username = '';
30
- this._files = [];
31
- this.isPublic = false;
32
- this.allowCors = false;
33
- this._gistIdentifierName = (0, formatted_gist_identifier_1.default)(_pureGistIdentifierName);
34
- }
35
- get gistId() {
36
- return this._gistId;
37
- }
38
- get username() {
39
- return this._username;
40
- }
41
- touch() {
42
- return __awaiter(this, void 0, void 0, function* () {
43
- yield (0, token_validity_1.default)(this.personalAccessToken);
44
- yield this._fetchGistIfExists();
45
- if ((0, is_string_empty_1.default)(this._gistId)) {
46
- yield this._createGistForFirstTime();
47
- }
48
- });
49
- }
50
- createFile(name, initialContent) {
51
- for (const file of this._files) {
52
- if (file.name === name) {
53
- throw new Error(`A file named ${name} already exists.`);
54
- }
55
- }
56
- const file = new file_1.default(this, name, initialContent);
57
- this._files.push(file);
58
- }
59
- getFile(name) {
60
- for (const file of this._files) {
61
- if (file.name === name) {
62
- return file;
63
- }
64
- }
65
- throw new Error('No file found with name: ' + name);
66
- }
67
- getFileNames() {
68
- return this._files.map(file => file.name);
69
- }
70
- save() {
71
- return __awaiter(this, void 0, void 0, function* () {
72
- const files = {};
73
- for (const file of this._files) {
74
- if (file.hasUpdates) {
75
- files[file.name] = {
76
- content: file.getContent()
77
- };
78
- }
79
- }
80
- if (Object.keys(files).length === 0) {
81
- // All files are already updated
82
- return;
83
- }
84
- const url = `${constants_1.default.githubGists}/${this.gistId}`;
85
- const body = {
86
- public: this.isPublic,
87
- files
88
- };
89
- try {
90
- yield axios_1.default.post(url, body, this._authConfig());
91
- }
92
- catch (e) {
93
- throw new Error('One or more files couldn\'t be saved.');
94
- }
95
- });
96
- }
97
- _fetchGistIfExists() {
98
- return __awaiter(this, void 0, void 0, function* () {
99
- let result;
100
- try {
101
- result = yield axios_1.default.get(constants_1.default.githubGists, this._authConfig());
102
- }
103
- catch (e) {
104
- throw new Error('Error while fetching gists.');
105
- }
106
- const gists = result.data;
107
- for (const gist of gists) {
108
- const fileNames = Object.keys(gist.files);
109
- if (fileNames.includes(this._gistIdentifierName)) {
110
- yield this._selfInitialize(gist);
111
- break;
112
- }
113
- }
114
- });
115
- }
116
- _createGistForFirstTime() {
117
- return __awaiter(this, void 0, void 0, function* () {
118
- const rootFileContent = constants_1.default.identifier
119
- .content.replace('<APP-NAME>', this._pureGistIdentifierName);
120
- const data = {
121
- public: this.isPublic,
122
- files: {
123
- [this._gistIdentifierName]: {
124
- content: rootFileContent
125
- }
126
- }
127
- };
128
- let result;
129
- try {
130
- result = yield axios_1.default.post(constants_1.default.githubGists, data, this._authConfig());
131
- }
132
- catch (e) {
133
- throw new Error('Error while creating the gist.');
134
- }
135
- yield this._selfInitialize(result.data);
136
- });
137
- }
138
- _getLatestCommit() {
139
- return __awaiter(this, void 0, void 0, function* () {
140
- const dummyParam = `dummyParam=${Math.random()}`;
141
- const url = `${constants_1.default.githubGists}/${this._gistId}?${dummyParam}`;
142
- try {
143
- const result = yield axios_1.default.get(url, this._authConfig());
144
- const response = result.data;
145
- const latestCommit = response.history[0];
146
- return latestCommit.version;
147
- }
148
- catch (e) {
149
- throw new Error('Error while fetching the latest commit.');
150
- }
151
- });
152
- }
153
- _selfInitialize(gist) {
154
- return __awaiter(this, void 0, void 0, function* () {
155
- this._gistId = gist.id;
156
- this._username = gist.owner.login;
157
- for (const fileName in gist.files) {
158
- if (gist.files.hasOwnProperty(fileName)) {
159
- const file = new file_1.default(this, fileName, '');
160
- yield file.fetchLatest();
161
- this._files.push(file);
162
- }
163
- }
164
- });
165
- }
166
- _authConfig() {
167
- return {
168
- headers: { Authorization: `token ${this.personalAccessToken}` }
169
- };
170
- }
171
- }
172
- exports.GithubGistApi = GithubGistApi;
173
- GithubGistApi.__getHelloWorldString = exports.getHelloWorldString;
3
+ const GithubGist_1 = require("./models/GithubGist");
4
+ exports.default = GithubGist_1.default;
@@ -0,0 +1,53 @@
1
+ interface GistFileOptions {
2
+ personalAccessToken: string;
3
+ gistId: string;
4
+ gistOwner: string;
5
+ fileName: string;
6
+ fileContent: string;
7
+ isPublic: boolean;
8
+ cors?: {
9
+ addPrefix?: boolean;
10
+ customPrefix?: (url: string) => string;
11
+ };
12
+ }
13
+ declare class GistFile {
14
+ private readonly personalAccessToken;
15
+ private readonly gistId;
16
+ private readonly gistOwner;
17
+ private readonly fileName;
18
+ private fileContent;
19
+ private fileHasUpdates;
20
+ private readonly isPublic;
21
+ private readonly addCorsPrefix;
22
+ private readonly customCorsPrefix?;
23
+ get hasUpdates(): boolean;
24
+ get name(): string;
25
+ get content(): string;
26
+ set hasUpdates(value: boolean);
27
+ constructor(options: GistFileOptions);
28
+ /**
29
+ * Over-write the file's content with new content
30
+ *
31
+ * @param newContent
32
+ */
33
+ overwrite: (newContent: string) => void;
34
+ /**
35
+ * Save the gist-file
36
+ */
37
+ save: () => Promise<void>;
38
+ /**
39
+ * Fetch the latest version of the file
40
+ */
41
+ fetchLatest: () => Promise<void>;
42
+ /**
43
+ * [Private Member] Returns the latest fetch url for the file. It gets updated on commit changes.
44
+ *
45
+ * @param commitId
46
+ */
47
+ private getLatestGistFileFetchUrl;
48
+ /**
49
+ * Returns the latest commit of the gist
50
+ */
51
+ private getLatestGistCommit;
52
+ }
53
+ export default GistFile;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const axios_1 = require("axios");
13
+ const auth_config_1 = require("../util/auth-config");
14
+ const constants_1 = require("../constants");
15
+ class GistFile {
16
+ constructor(options) {
17
+ var _a, _b;
18
+ this.gistOwner = '';
19
+ this.fileHasUpdates = false;
20
+ /**
21
+ * Over-write the file's content with new content
22
+ *
23
+ * @param newContent
24
+ */
25
+ this.overwrite = (newContent) => {
26
+ this.fileContent = newContent;
27
+ this.fileHasUpdates = true;
28
+ };
29
+ /**
30
+ * Save the gist-file
31
+ */
32
+ this.save = () => __awaiter(this, void 0, void 0, function* () {
33
+ if (this.hasUpdates === false)
34
+ return;
35
+ const url = `${constants_1.default.githubGists}/${this.gistId}`;
36
+ const body = {
37
+ public: this.isPublic,
38
+ files: {
39
+ [this.fileName]: {
40
+ content: this.fileContent
41
+ }
42
+ }
43
+ };
44
+ yield axios_1.default.post(url, body, (0, auth_config_1.default)({ personalAccessToken: this.personalAccessToken }));
45
+ this.fileHasUpdates = false;
46
+ });
47
+ /**
48
+ * Fetch the latest version of the file
49
+ */
50
+ this.fetchLatest = () => __awaiter(this, void 0, void 0, function* () {
51
+ const latestCommit = yield this.getLatestGistCommit();
52
+ const url = this.getLatestGistFileFetchUrl(latestCommit);
53
+ this.fileContent = yield axios_1.default.get(url, (0, auth_config_1.default)({ personalAccessToken: this.personalAccessToken }));
54
+ this.fileHasUpdates = false;
55
+ });
56
+ /**
57
+ * [Private Member] Returns the latest fetch url for the file. It gets updated on commit changes.
58
+ *
59
+ * @param commitId
60
+ */
61
+ this.getLatestGistFileFetchUrl = (commitId) => {
62
+ const { addCorsPrefix, customCorsPrefix, gistOwner, gistId, } = this;
63
+ const url = `https://gist.githubusercontent.com/${gistOwner}` +
64
+ `/${gistId}/raw/${commitId}/${this.fileName}`;
65
+ if (addCorsPrefix === false)
66
+ return url;
67
+ if (customCorsPrefix)
68
+ return customCorsPrefix(url);
69
+ return constants_1.default.corsAnywhere + url;
70
+ };
71
+ /**
72
+ * Returns the latest commit of the gist
73
+ */
74
+ this.getLatestGistCommit = () => __awaiter(this, void 0, void 0, function* () {
75
+ const dummyParam = `dummyParam=${Math.random()}`; // So that we are not a victim of caching
76
+ const url = `${constants_1.default.githubGists}/${this.gistId}?${dummyParam}`;
77
+ try {
78
+ const result = yield axios_1.default.get(url, (0, auth_config_1.default)({ personalAccessToken: this.personalAccessToken }));
79
+ const response = result.data;
80
+ const latestCommit = response.history[0];
81
+ return latestCommit.version;
82
+ }
83
+ catch (e) {
84
+ throw new Error('Error while fetching the latest commit.');
85
+ }
86
+ });
87
+ this.personalAccessToken = options.personalAccessToken;
88
+ this.gistId = options.gistId;
89
+ this.gistOwner = options.gistOwner;
90
+ this.fileName = options.fileName;
91
+ this.fileContent = options.fileContent;
92
+ this.isPublic = options.isPublic;
93
+ this.fileHasUpdates = true;
94
+ this.addCorsPrefix = Boolean((_a = options.cors) === null || _a === void 0 ? void 0 : _a.addPrefix);
95
+ this.customCorsPrefix = (_b = options.cors) === null || _b === void 0 ? void 0 : _b.customPrefix;
96
+ }
97
+ // Getters
98
+ get hasUpdates() { return this.fileHasUpdates; }
99
+ get name() { return this.fileName; }
100
+ get content() { return this.fileContent; }
101
+ // Setters
102
+ set hasUpdates(value) { this.fileHasUpdates = value; }
103
+ ;
104
+ }
105
+ exports.default = GistFile;
@@ -0,0 +1,109 @@
1
+ import GistFile from "./GistFile";
2
+ interface GithubGistOptions {
3
+ /**
4
+ * Head over to this link: https://github.com/settings/tokens/new?scopes=gist to create your personalAccessToken.
5
+ * The "gist" scope is needed. Keep that token, a secret.
6
+ */
7
+ personalAccessToken: string;
8
+ /**
9
+ * A unique name to identify your app. This is used to identify which files in the gist are managed by this lib.
10
+ * Be sure to use the same name everytime so that you are modifying same files from your previous session.
11
+ *
12
+ * Examples: my-chat-app, my-first-app
13
+ *
14
+ * Note: Do use same identifier when re-starting the application. This is the thing that will be used to identify
15
+ * your previously stored file in the Gist. For different applications, use different identifiers, unless you want
16
+ * to share the files in the gist among different applications.
17
+ */
18
+ appIdentifier: string;
19
+ /**
20
+ * Whether the gist should be private or public (If public, it would be accessible for reading to everyone)
21
+ *
22
+ * Default: undefined -> which means, Private
23
+ */
24
+ isPublic?: boolean;
25
+ /**
26
+ * CORS configuration: Not needed when using server-side.
27
+ */
28
+ cors?: {
29
+ /**
30
+ * Adds the default proxy-server prefix so that the URLs are not CORS blocked.
31
+ *
32
+ * For example: https://cors-anywhere.herokuapp.com/ as prefix to the Url.
33
+ */
34
+ addPrefix?: boolean;
35
+ /**
36
+ * Gets the URL as argument. Feel free to decorate with any of your URLs and then
37
+ * return the decorated URL.
38
+ */
39
+ customPrefix?: (url: string) => string;
40
+ };
41
+ }
42
+ declare class GithubGist {
43
+ private readonly personalAccessToken;
44
+ private readonly appIdentifier;
45
+ private readonly formattedAppIdentifier;
46
+ private gistId;
47
+ private gistOwner;
48
+ private gistFiles;
49
+ private readonly isPublic;
50
+ private readonly addCorsPrefix;
51
+ private readonly customCorsPrefix?;
52
+ get id(): string;
53
+ get ownerUsername(): string;
54
+ constructor(options: GithubGistOptions);
55
+ /**
56
+ * Syncs the gistInstance with Github server. Should be done only once,
57
+ * right after instantiation of this class.
58
+ */
59
+ touch: () => Promise<void>;
60
+ /**
61
+ * Creates a file in the gist. If file already exists, it over-writes the
62
+ * content of the file.
63
+ * Returns, true, if file was created.
64
+ * Returns, false, if existing file was updated.
65
+ *
66
+ * @param name
67
+ * @param content
68
+ */
69
+ createFile: (name: string, content: string) => boolean;
70
+ /**
71
+ * Get a particular file instance. Returns null if file not found.
72
+ *
73
+ * @param name
74
+ */
75
+ getFile: (name: string) => GistFile | null;
76
+ /**
77
+ * Get all file instances
78
+ */
79
+ getFiles: () => GistFile[];
80
+ /**
81
+ * Returns the names of all the files in the gist.
82
+ */
83
+ getFileNames: () => string[];
84
+ /**
85
+ * Saves all the files in the gist, only if they have updates
86
+ */
87
+ save: () => Promise<void>;
88
+ /**
89
+ * [Private Member] Fetches the gist information.
90
+ */
91
+ private fetchGist;
92
+ /**
93
+ * [Private Member] Creates the gist
94
+ */
95
+ private createGist;
96
+ /**
97
+ * [Private Member] Initializes the instance with the information from server.
98
+ * @param gist
99
+ * @private
100
+ */
101
+ private initialize;
102
+ /**
103
+ * [Private Member] This constructs the GistFile instance
104
+ * @param fileName
105
+ * @param content
106
+ */
107
+ private constructGistFile;
108
+ }
109
+ export default GithubGist;
@@ -0,0 +1,193 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const axios_1 = require("axios");
13
+ const auth_config_1 = require("../util/auth-config");
14
+ const token_validity_1 = require("../util/token-validity");
15
+ const is_string_empty_1 = require("../util/is-string-empty");
16
+ const formatted_gist_identifier_1 = require("../util/formatted-gist-identifier");
17
+ const constants_1 = require("../constants");
18
+ const GistFile_1 = require("./GistFile");
19
+ class GithubGist {
20
+ constructor(options) {
21
+ var _a, _b;
22
+ this.gistId = '';
23
+ this.gistOwner = '';
24
+ this.gistFiles = [];
25
+ /**
26
+ * Syncs the gistInstance with Github server. Should be done only once,
27
+ * right after instantiation of this class.
28
+ */
29
+ this.touch = () => __awaiter(this, void 0, void 0, function* () {
30
+ // Throws error if the token is not valid.
31
+ yield (0, token_validity_1.default)(this.personalAccessToken);
32
+ // Fetch and set the gist ID
33
+ yield this.fetchGist();
34
+ // If gist ID is not set, it means the Gist doesn't exist. Create a new gist
35
+ if ((0, is_string_empty_1.default)(this.gistId)) {
36
+ yield this.createGist();
37
+ }
38
+ });
39
+ /**
40
+ * Creates a file in the gist. If file already exists, it over-writes the
41
+ * content of the file.
42
+ * Returns, true, if file was created.
43
+ * Returns, false, if existing file was updated.
44
+ *
45
+ * @param name
46
+ * @param content
47
+ */
48
+ this.createFile = (name, content) => {
49
+ const existingFile = this.gistFiles.find((file) => file.name === name);
50
+ if (existingFile) {
51
+ existingFile.overwrite(content);
52
+ return false;
53
+ }
54
+ const file = this.constructGistFile(name, content);
55
+ this.gistFiles.push(file);
56
+ return true;
57
+ };
58
+ /**
59
+ * Get a particular file instance. Returns null if file not found.
60
+ *
61
+ * @param name
62
+ */
63
+ this.getFile = (name) => {
64
+ const file = this.gistFiles.find((file) => file.name === name);
65
+ if (file)
66
+ return file;
67
+ // File not found
68
+ return null;
69
+ };
70
+ /**
71
+ * Get all file instances
72
+ */
73
+ this.getFiles = () => {
74
+ return [...this.gistFiles];
75
+ };
76
+ /**
77
+ * Returns the names of all the files in the gist.
78
+ */
79
+ this.getFileNames = () => {
80
+ return this.gistFiles.map(file => file.name);
81
+ };
82
+ /**
83
+ * Saves all the files in the gist, only if they have updates
84
+ */
85
+ this.save = () => __awaiter(this, void 0, void 0, function* () {
86
+ const files = {};
87
+ for (const file of this.gistFiles) {
88
+ if (file.hasUpdates === false)
89
+ continue;
90
+ files[file.name] = {
91
+ content: file.content,
92
+ };
93
+ }
94
+ // No files need updates
95
+ if (Object.keys(files).length === 0)
96
+ return;
97
+ const url = `${constants_1.default.githubGists}/${this.gistId}`;
98
+ const body = { public: this.isPublic, files };
99
+ yield axios_1.default.post(url, body, (0, auth_config_1.default)({ personalAccessToken: this.personalAccessToken }));
100
+ // Mark the hasUpdates flag in all the files as false.
101
+ this.gistFiles.forEach((file) => {
102
+ file.hasUpdates = false;
103
+ });
104
+ });
105
+ /**
106
+ * [Private Member] Fetches the gist information.
107
+ */
108
+ this.fetchGist = () => __awaiter(this, void 0, void 0, function* () {
109
+ // Gets all the gists basic information
110
+ const result = yield axios_1.default.get(constants_1.default.githubGists, (0, auth_config_1.default)({ personalAccessToken: this.personalAccessToken }));
111
+ const gists = result.data;
112
+ for (const gist of gists) {
113
+ const fileNames = Object.keys(gist.files);
114
+ // If the formattedAppIdentifier file exists in gist, this is out gist.
115
+ if (fileNames.includes(this.formattedAppIdentifier)) {
116
+ yield this.initialize(gist);
117
+ break;
118
+ }
119
+ }
120
+ });
121
+ /**
122
+ * [Private Member] Creates the gist
123
+ */
124
+ this.createGist = () => __awaiter(this, void 0, void 0, function* () {
125
+ const { identifier: { content }, githubGists } = constants_1.default;
126
+ const rootFileContent = content.replace('<APP-NAME>', this.appIdentifier);
127
+ const payload = {
128
+ public: this.isPublic,
129
+ files: {
130
+ [this.formattedAppIdentifier]: {
131
+ content: rootFileContent
132
+ }
133
+ }
134
+ };
135
+ // Create gist API call
136
+ const result = yield axios_1.default.post(githubGists, payload, (0, auth_config_1.default)({ personalAccessToken: this.personalAccessToken }));
137
+ const gist = result.data;
138
+ // Initialize the current instance with the gist meta-information
139
+ yield this.initialize(gist);
140
+ });
141
+ /**
142
+ * [Private Member] Initializes the instance with the information from server.
143
+ * @param gist
144
+ * @private
145
+ */
146
+ this.initialize = (gist) => __awaiter(this, void 0, void 0, function* () {
147
+ // Set gist meta
148
+ this.gistId = gist.id;
149
+ this.gistOwner = gist.owner.login;
150
+ const fetchFileContent = [];
151
+ // Initialize all the files
152
+ this.gistFiles = [];
153
+ for (const fileName of Object.keys(gist.files)) {
154
+ const file = this.constructGistFile(fileName, '');
155
+ fetchFileContent.push(file.fetchLatest());
156
+ this.gistFiles.push(file);
157
+ }
158
+ // Fetching content of all the files.
159
+ yield Promise.all(fetchFileContent);
160
+ });
161
+ /**
162
+ * [Private Member] This constructs the GistFile instance
163
+ * @param fileName
164
+ * @param content
165
+ */
166
+ this.constructGistFile = (fileName, content) => {
167
+ return new GistFile_1.default({
168
+ fileName,
169
+ fileContent: content,
170
+ gistId: this.gistId,
171
+ gistOwner: this.gistOwner,
172
+ cors: {
173
+ addPrefix: this.addCorsPrefix,
174
+ customPrefix: this.customCorsPrefix,
175
+ },
176
+ personalAccessToken: this.personalAccessToken,
177
+ isPublic: this.isPublic,
178
+ });
179
+ };
180
+ this.personalAccessToken = options.personalAccessToken;
181
+ this.appIdentifier = options.appIdentifier;
182
+ this.formattedAppIdentifier = (0, formatted_gist_identifier_1.default)(options.appIdentifier);
183
+ this.isPublic = Boolean(options.isPublic);
184
+ this.addCorsPrefix = Boolean((_a = options.cors) === null || _a === void 0 ? void 0 : _a.addPrefix);
185
+ this.customCorsPrefix = (_b = options.cors) === null || _b === void 0 ? void 0 : _b.customPrefix;
186
+ }
187
+ // Getters
188
+ get id() { return this.gistId; }
189
+ ;
190
+ get ownerUsername() { return this.gistOwner; }
191
+ ;
192
+ }
193
+ exports.default = GithubGist;
@@ -0,0 +1,6 @@
1
+ import { AxiosRequestConfig } from "axios";
2
+ interface AuthConfigProps {
3
+ personalAccessToken: string;
4
+ }
5
+ declare const getAuthConfig: (props: AuthConfigProps) => AxiosRequestConfig;
6
+ export default getAuthConfig;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const getAuthConfig = (props) => {
4
+ return {
5
+ headers: { Authorization: `token ${props.personalAccessToken}` }
6
+ };
7
+ };
8
+ exports.default = getAuthConfig;
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- const constants_1 = require("./constants");
13
12
  const axios_1 = require("axios");
13
+ const constants_1 = require("../constants");
14
14
  const isTokenStringValid = (token) => __awaiter(void 0, void 0, void 0, function* () {
15
15
  const rateLimitEndpoint = constants_1.default.githubRateLimit;
16
16
  return axios_1.default
package/package.json CHANGED
@@ -1,20 +1,31 @@
1
1
  {
2
2
  "name": "simple-github-gist-api",
3
- "version": "2.0.3",
3
+ "version": "2.0.7",
4
4
  "description": "A way to store data on Github Gist.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "test": "jest --config jestconfig.json",
9
- "build": "rm -rf dist/ && tsc",
10
- "postpublish": "PACKAGE_VERSION=$(cat package.json | grep \\\"version\\\" | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag v$PACKAGE_VERSION && git push --tags"
9
+ "prepublish": "npm run build",
10
+ "postpublish": "PACKAGE_VERSION=$(cat package.json | grep \\\"version\\\" | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag v$PACKAGE_VERSION && git push --tags",
11
+ "prepare": "husky install",
12
+ "cleanup": "rimraf dist",
13
+ "build:pre-requisite": "npm run test",
14
+ "build:declaration": "tsc",
15
+ "build": "npm run cleanup && npm run build:pre-requisite && npm-run-all build:*",
16
+ "test:watch": "jest --watch",
17
+ "prettier:fix": "prettier -w ./src/**/*.ts -w ./src/**/*.tsx --no-error-on-unmatched-pattern true",
18
+ "lint:fix": "eslint --fix ./src/**/*.ts --fix ./src/**/*.tsx --no-error-on-unmatched-pattern true",
19
+ "git:rebase": "git fetch && git rebase origin/master",
20
+ "release": "npm run git:rebase && npm run build && standard-version && git push --follow-tags && npm publish --access=public",
21
+ "lint": "eslint src/*"
11
22
  },
12
23
  "files": [
13
24
  "dist/**/*"
14
25
  ],
15
26
  "repository": {
16
27
  "type": "git",
17
- "url": "git+ssh://git@github.com:rv-npm/simple-github-gist-api.git"
28
+ "url": "git+ssh://git@github.com:vighnesh153/simple-github-gist-api.git"
18
29
  },
19
30
  "keywords": [
20
31
  "gist",
@@ -27,16 +38,35 @@
27
38
  "author": "Vighnesh Raut",
28
39
  "license": "GPL-3.0-or-later",
29
40
  "bugs": {
30
- "url": "https://github.com/rv-npm/simple-github-gist-api/issues"
41
+ "url": "https://github.com/vighnesh153/simple-github-gist-api/issues"
31
42
  },
32
- "homepage": "https://github.com/rv-npm/simple-github-gist-api#readme",
43
+ "homepage": "https://github.com/vighnesh153/simple-github-gist-api#readme",
33
44
  "devDependencies": {
45
+ "@commitlint/cli": "^15.0.0",
46
+ "@commitlint/config-conventional": "^15.0.0",
34
47
  "@types/jest": "^27.0.2",
48
+ "eslint": "^8.4.1",
49
+ "eslint-config-airbnb": "^19.0.2",
50
+ "eslint-config-node": "^4.1.0",
51
+ "eslint-config-prettier": "^8.3.0",
52
+ "eslint-plugin-import": "^2.25.3",
53
+ "eslint-plugin-jsx-a11y": "^6.5.1",
54
+ "eslint-plugin-node": "^11.1.0",
55
+ "eslint-plugin-prettier": "^4.0.0",
56
+ "eslint-plugin-react": "^7.27.1",
57
+ "eslint-plugin-react-hooks": "^4.3.0",
58
+ "husky": "^7.0.4",
35
59
  "jest": "^27.3.0",
60
+ "lint-staged": "^12.1.2",
61
+ "npm-run-all": "^4.1.5",
62
+ "prettier": "^2.5.1",
63
+ "rimraf": "^3.0.2",
64
+ "semantic-release": "^18.0.1",
65
+ "standard-version": "^9.3.2",
36
66
  "ts-jest": "^27.0.7",
37
67
  "typescript": "^4.4.4"
38
68
  },
39
69
  "dependencies": {
40
- "axios": "^0.23.0"
70
+ "axios": "^0.24.0"
41
71
  }
42
72
  }
@@ -1,15 +0,0 @@
1
- import { GithubGistApi } from '../index';
2
- export default class File {
3
- private _rootRef;
4
- private _fileName;
5
- private _content;
6
- private _hasUpdates;
7
- get hasUpdates(): boolean;
8
- get name(): string;
9
- constructor(_rootRef: GithubGistApi, _fileName: string, _content: string);
10
- getContent(): string;
11
- overwrite(newContent: string): void;
12
- save(): Promise<void>;
13
- fetchLatest(): Promise<void>;
14
- private _latestFetchUrl;
15
- }
@@ -1,75 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- const constants_1 = require("../constants");
13
- const axios_1 = require("axios");
14
- class File {
15
- constructor(_rootRef, _fileName, _content) {
16
- this._rootRef = _rootRef;
17
- this._fileName = _fileName;
18
- this._content = _content;
19
- this._hasUpdates = true;
20
- }
21
- get hasUpdates() {
22
- return this._hasUpdates;
23
- }
24
- get name() {
25
- return this._fileName;
26
- }
27
- getContent() {
28
- return this._content;
29
- }
30
- overwrite(newContent) {
31
- this._content = newContent;
32
- this._hasUpdates = true;
33
- }
34
- save() {
35
- return __awaiter(this, void 0, void 0, function* () {
36
- const url = `${constants_1.default.githubGists}/${this._rootRef.gistId}`;
37
- const body = {
38
- public: this._rootRef.isPublic,
39
- files: {
40
- [this._fileName]: {
41
- content: this._content
42
- }
43
- }
44
- };
45
- try {
46
- yield axios_1.default.post(url, body, this._rootRef._authConfig());
47
- }
48
- catch (e) {
49
- throw new Error('Couldn\'t save file: ' + this._fileName);
50
- }
51
- this._hasUpdates = false;
52
- });
53
- }
54
- fetchLatest() {
55
- return __awaiter(this, void 0, void 0, function* () {
56
- const latestCommit = yield this._rootRef._getLatestCommit();
57
- const url = this._latestFetchUrl(latestCommit);
58
- try {
59
- this._content = yield axios_1.default.get(url, this._rootRef._authConfig());
60
- }
61
- catch (e) {
62
- throw new Error('Couldn\'t fetch latest data of ' + this._fileName);
63
- }
64
- this._hasUpdates = false;
65
- });
66
- }
67
- _latestFetchUrl(commitId) {
68
- const { allowCors, username, gistId, } = this._rootRef;
69
- const corsPrefix = allowCors ? constants_1.default.corsAnywhere : '';
70
- return `${corsPrefix}` +
71
- `https://gist.githubusercontent.com/${username}` +
72
- `/${gistId}/raw/${commitId}/${this._fileName}`;
73
- }
74
- }
75
- exports.default = File;
@@ -1,5 +0,0 @@
1
- export default interface GistAuthConfig {
2
- headers: {
3
- Authorization: string;
4
- };
5
- }
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,13 +0,0 @@
1
- interface GistFile {
2
- [key: string]: {
3
- filename: string;
4
- };
5
- }
6
- export default interface Gist {
7
- id: string;
8
- owner: {
9
- login: string;
10
- };
11
- files: GistFile;
12
- }
13
- export {};
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +0,0 @@
1
- declare const required: (v: string) => never;
2
- export default required;
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const required = (v) => {
4
- throw new Error(`Argument "${v}" is required!`);
5
- };
6
- exports.default = required;