@helloao/cli 0.0.1
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/actions.d.ts +57 -0
- package/actions.js +262 -0
- package/cli.d.ts +2 -0
- package/cli.js +139 -0
- package/db.d.ts +110 -0
- package/db.js +754 -0
- package/downloads.d.ts +2 -0
- package/downloads.js +12 -0
- package/files.d.ts +56 -0
- package/files.js +232 -0
- package/index.d.ts +8 -0
- package/index.js +38 -0
- package/migrations/20240420231455_initial/migration.sql +66 -0
- package/migrations/20240623183848_add_book_order/migration.sql +26 -0
- package/migrations/20240629194121_add_chapter_links/migration.sql +45 -0
- package/migrations/20240629194513_add_chapter_content/migration.sql +30 -0
- package/migrations/20240705221833_remove_unused_columns/migration.sql +27 -0
- package/migrations/20240711173108_add_chapter_audio/migration.sql +13 -0
- package/migrations/20240724212651_add_hashing/migration.sql +25 -0
- package/node_modules/@zip.js/zip.js/LICENSE +28 -0
- package/node_modules/@zip.js/zip.js/README.md +173 -0
- package/node_modules/@zip.js/zip.js/deno.json +8 -0
- package/node_modules/@zip.js/zip.js/dist/README.md +28 -0
- package/node_modules/@zip.js/zip.js/dist/z-worker-fflate.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/z-worker-pako.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/z-worker.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/zip-fs-full.js +11935 -0
- package/node_modules/@zip.js/zip.js/dist/zip-fs-full.min.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/zip-fs.js +6079 -0
- package/node_modules/@zip.js/zip.js/dist/zip-fs.min.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/zip-full.js +9463 -0
- package/node_modules/@zip.js/zip.js/dist/zip-full.min.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/zip-no-worker-deflate.min.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/zip-no-worker-inflate.min.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/zip-no-worker.min.js +1 -0
- package/node_modules/@zip.js/zip.js/dist/zip.js +5240 -0
- package/node_modules/@zip.js/zip.js/dist/zip.min.js +1 -0
- package/node_modules/@zip.js/zip.js/index-fflate.js +82 -0
- package/node_modules/@zip.js/zip.js/index.cjs +11927 -0
- package/node_modules/@zip.js/zip.js/index.d.ts +2048 -0
- package/node_modules/@zip.js/zip.js/index.js +87 -0
- package/node_modules/@zip.js/zip.js/index.min.js +1 -0
- package/node_modules/@zip.js/zip.js/lib/core/codec-pool.js +127 -0
- package/node_modules/@zip.js/zip.js/lib/core/codec-worker.js +348 -0
- package/node_modules/@zip.js/zip.js/lib/core/configuration.js +127 -0
- package/node_modules/@zip.js/zip.js/lib/core/constants.js +114 -0
- package/node_modules/@zip.js/zip.js/lib/core/io.js +749 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/aes-crypto-stream.js +326 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/codec-stream.js +154 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/codecs/crc32.js +63 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/codecs/deflate.js +2063 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/codecs/inflate.js +2167 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/codecs/sjcl.js +827 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/common-crypto.js +55 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/crc32-stream.js +56 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/stream-adapter.js +55 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/zip-crypto-stream.js +162 -0
- package/node_modules/@zip.js/zip.js/lib/core/streams/zip-entry-stream.js +165 -0
- package/node_modules/@zip.js/zip.js/lib/core/util/cp437-decode.js +48 -0
- package/node_modules/@zip.js/zip.js/lib/core/util/decode-text.js +43 -0
- package/node_modules/@zip.js/zip.js/lib/core/util/default-mime-type.js +38 -0
- package/node_modules/@zip.js/zip.js/lib/core/util/encode-text.js +48 -0
- package/node_modules/@zip.js/zip.js/lib/core/util/mime-type.js +1639 -0
- package/node_modules/@zip.js/zip.js/lib/core/util/stream-codec-shim.js +91 -0
- package/node_modules/@zip.js/zip.js/lib/core/z-worker-core.js +176 -0
- package/node_modules/@zip.js/zip.js/lib/core/zip-entry.js +86 -0
- package/node_modules/@zip.js/zip.js/lib/core/zip-fs-core.js +865 -0
- package/node_modules/@zip.js/zip.js/lib/core/zip-reader.js +757 -0
- package/node_modules/@zip.js/zip.js/lib/core/zip-writer.js +1186 -0
- package/node_modules/@zip.js/zip.js/lib/z-worker-bootstrap-fflate.js +40 -0
- package/node_modules/@zip.js/zip.js/lib/z-worker-bootstrap-pako.js +39 -0
- package/node_modules/@zip.js/zip.js/lib/z-worker-fflate.js +40 -0
- package/node_modules/@zip.js/zip.js/lib/z-worker-inline-template.js +42 -0
- package/node_modules/@zip.js/zip.js/lib/z-worker-inline.js +1 -0
- package/node_modules/@zip.js/zip.js/lib/z-worker.js +38 -0
- package/node_modules/@zip.js/zip.js/lib/zip-data-uri.js +53 -0
- package/node_modules/@zip.js/zip.js/lib/zip-fflate-shim.js +37 -0
- package/node_modules/@zip.js/zip.js/lib/zip-fs.js +53 -0
- package/node_modules/@zip.js/zip.js/lib/zip-full-fflate.js +53 -0
- package/node_modules/@zip.js/zip.js/lib/zip-full.js +54 -0
- package/node_modules/@zip.js/zip.js/lib/zip-no-worker-deflate.js +42 -0
- package/node_modules/@zip.js/zip.js/lib/zip-no-worker-fflate-deflate.js +42 -0
- package/node_modules/@zip.js/zip.js/lib/zip-no-worker-fflate-inflate.js +42 -0
- package/node_modules/@zip.js/zip.js/lib/zip-no-worker-fflate.js +43 -0
- package/node_modules/@zip.js/zip.js/lib/zip-no-worker-inflate.js +42 -0
- package/node_modules/@zip.js/zip.js/lib/zip-no-worker.js +44 -0
- package/node_modules/@zip.js/zip.js/lib/zip.js +52 -0
- package/node_modules/@zip.js/zip.js/package.json +86 -0
- package/package.json +43 -0
- package/prisma-gen/default.d.ts +1 -0
- package/prisma-gen/default.js +1 -0
- package/prisma-gen/edge.d.ts +1 -0
- package/prisma-gen/edge.js +242 -0
- package/prisma-gen/index-browser.js +236 -0
- package/prisma-gen/index.d.ts +13248 -0
- package/prisma-gen/index.js +265 -0
- package/prisma-gen/runtime/edge-esm.js +28 -0
- package/prisma-gen/runtime/edge.js +28 -0
- package/prisma-gen/runtime/index-browser.d.ts +365 -0
- package/prisma-gen/runtime/index-browser.js +13 -0
- package/prisma-gen/runtime/library.d.ts +3168 -0
- package/prisma-gen/runtime/library.js +140 -0
- package/prisma-gen/runtime/wasm.js +29 -0
- package/prisma-gen/wasm.d.ts +1 -0
- package/prisma-gen/wasm.js +236 -0
- package/s3.d.ts +14 -0
- package/s3.js +76 -0
- package/schema.prisma +154 -0
- package/uploads.d.ts +54 -0
- package/uploads.js +141 -0
package/downloads.d.ts
ADDED
package/downloads.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.downloadFile = downloadFile;
|
|
4
|
+
const fs_extra_1 = require("fs-extra");
|
|
5
|
+
const node_stream_1 = require("node:stream");
|
|
6
|
+
const promises_1 = require("node:stream/promises");
|
|
7
|
+
async function downloadFile(url, path) {
|
|
8
|
+
console.log('Downloading', url, 'to', path);
|
|
9
|
+
const reader = await fetch(url).then(r => r.body);
|
|
10
|
+
const writeStream = (0, fs_extra_1.createWriteStream)(path);
|
|
11
|
+
await (0, promises_1.finished)(node_stream_1.Readable.fromWeb(reader).pipe(writeStream));
|
|
12
|
+
}
|
package/files.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { InputFile } from "@helloao/tools/generation/common-types";
|
|
2
|
+
import { SerializedFile, Uploader } from "./db";
|
|
3
|
+
/**
|
|
4
|
+
* Loads the files for the given translations.
|
|
5
|
+
* @param dir The directory that the translations exist in.
|
|
6
|
+
*/
|
|
7
|
+
export declare function loadTranslationsFiles(dirs: string[]): Promise<InputFile[]>;
|
|
8
|
+
/**
|
|
9
|
+
* Loads the files for the given translation.
|
|
10
|
+
* @param translation The directory that the translation exists in.
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadTranslationFiles(translation: string): Promise<InputFile[]>;
|
|
14
|
+
export interface CollectionTranslationMetadata {
|
|
15
|
+
name: {
|
|
16
|
+
local: string;
|
|
17
|
+
abbrev: string;
|
|
18
|
+
english: string;
|
|
19
|
+
};
|
|
20
|
+
language: string;
|
|
21
|
+
year: number;
|
|
22
|
+
direction: 'ltr' | 'rtl';
|
|
23
|
+
copyright: {
|
|
24
|
+
licenses: any[];
|
|
25
|
+
attribution: string;
|
|
26
|
+
attribution_url: string;
|
|
27
|
+
};
|
|
28
|
+
id: string | null;
|
|
29
|
+
source: {
|
|
30
|
+
id: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Defines an uploader that is able to upload files to a directory.
|
|
35
|
+
*/
|
|
36
|
+
export declare class FilesUploader implements Uploader {
|
|
37
|
+
private _dir;
|
|
38
|
+
constructor(dir: string);
|
|
39
|
+
get idealBatchSize(): number | null;
|
|
40
|
+
upload(file: SerializedFile, overwrite: boolean): Promise<boolean>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Defines an uploader that is able to upload files into a zip file.
|
|
44
|
+
*/
|
|
45
|
+
export declare class ZipUploader implements Uploader {
|
|
46
|
+
private _path;
|
|
47
|
+
private _initPromise;
|
|
48
|
+
private _fileHandle;
|
|
49
|
+
private _zip;
|
|
50
|
+
constructor(filePath: string);
|
|
51
|
+
private _init;
|
|
52
|
+
get idealBatchSize(): number | null;
|
|
53
|
+
upload(file: SerializedFile, _overwrite: boolean): Promise<boolean>;
|
|
54
|
+
dispose(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=files.d.ts.map
|
package/files.js
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.ZipUploader = exports.FilesUploader = void 0;
|
|
27
|
+
exports.loadTranslationsFiles = loadTranslationsFiles;
|
|
28
|
+
exports.loadTranslationFiles = loadTranslationFiles;
|
|
29
|
+
const promises_1 = require("fs/promises");
|
|
30
|
+
const path_1 = require("path");
|
|
31
|
+
const path = __importStar(require("path"));
|
|
32
|
+
const fs_extra_1 = require("fs-extra");
|
|
33
|
+
const zip_js_1 = require("@zip.js/zip.js");
|
|
34
|
+
const stream_1 = require("stream");
|
|
35
|
+
const hash_js_1 = require("hash.js");
|
|
36
|
+
const usx_parser_1 = require("@helloao/tools/parser/usx-parser");
|
|
37
|
+
/**
|
|
38
|
+
* Loads the files for the given translations.
|
|
39
|
+
* @param dir The directory that the translations exist in.
|
|
40
|
+
*/
|
|
41
|
+
async function loadTranslationsFiles(dirs) {
|
|
42
|
+
const promises = [];
|
|
43
|
+
for (let dir of dirs) {
|
|
44
|
+
const fullPath = path.resolve(dir);
|
|
45
|
+
promises.push(loadTranslationFiles(fullPath));
|
|
46
|
+
}
|
|
47
|
+
const allFiles = await Promise.all(promises);
|
|
48
|
+
const files = allFiles.flat();
|
|
49
|
+
return files;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Loads the files for the given translation.
|
|
53
|
+
* @param translation The directory that the translation exists in.
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
56
|
+
async function loadTranslationFiles(translation) {
|
|
57
|
+
const metadata = await loadTranslationMetadata(translation);
|
|
58
|
+
if (!metadata) {
|
|
59
|
+
console.error('Could not load metadata for translation!', translation);
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
let files = await (0, promises_1.readdir)(translation);
|
|
63
|
+
let usfmFiles = files.filter(f => (0, path_1.extname)(f) === '.usfm' || (0, path_1.extname)(f) === '.usx' || (0, path_1.extname)(f) === '.json');
|
|
64
|
+
if (usfmFiles.length <= 0) {
|
|
65
|
+
translation = path.resolve(translation, 'usfm');
|
|
66
|
+
if ((0, fs_extra_1.existsSync)(translation)) {
|
|
67
|
+
files = await (0, promises_1.readdir)(translation);
|
|
68
|
+
usfmFiles = files.filter(f => (0, path_1.extname)(f) === '.usfm');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (usfmFiles.length <= 0) {
|
|
72
|
+
console.error('Could not find USFM files for translation!', translation);
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
let promises = [];
|
|
76
|
+
for (let file of usfmFiles) {
|
|
77
|
+
if (path.parse(file).name === 'metadata') {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const filePath = path.resolve(translation, file);
|
|
81
|
+
promises.push(loadFile(filePath, {
|
|
82
|
+
translation: metadata
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
return await Promise.all(promises);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Loads the metadata for the given translation.
|
|
89
|
+
* @param translation The translation that the metadata should be loaded for.
|
|
90
|
+
* @returns
|
|
91
|
+
*/
|
|
92
|
+
async function loadTranslationMetadata(translation) {
|
|
93
|
+
const metadataTs = path.resolve(translation, 'metadata.ts');
|
|
94
|
+
if ((0, fs_extra_1.existsSync)(metadataTs)) {
|
|
95
|
+
return (await Promise.resolve(`${metadataTs}`).then(s => __importStar(require(s)))).default;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
const metadataJson = path.resolve(translation, 'meta.json');
|
|
99
|
+
if ((0, fs_extra_1.existsSync)(metadataJson)) {
|
|
100
|
+
const data = await (0, promises_1.readFile)(metadataJson, { encoding: 'utf-8' });
|
|
101
|
+
const metadata = JSON.parse(data);
|
|
102
|
+
return {
|
|
103
|
+
id: metadata.id ?? metadata.source.id,
|
|
104
|
+
language: metadata.language,
|
|
105
|
+
name: metadata.name.local,
|
|
106
|
+
englishName: metadata.name.english,
|
|
107
|
+
licenseUrl: metadata.copyright.attribution_url,
|
|
108
|
+
website: metadata.copyright.attribution_url,
|
|
109
|
+
shortName: metadata.name.abbrev,
|
|
110
|
+
direction: metadata.direction
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const metadataJson = path.resolve(translation, 'metadata.json');
|
|
115
|
+
if ((0, fs_extra_1.existsSync)(metadataJson)) {
|
|
116
|
+
const data = await (0, promises_1.readFile)(metadataJson, { encoding: 'utf-8' });
|
|
117
|
+
return JSON.parse(data);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
console.error('Could not find metadata for translation!', translation);
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Loads the file from the given path using the given metadata.
|
|
126
|
+
* @param file The file that should be loaded.
|
|
127
|
+
* @param metadata The metadata.
|
|
128
|
+
*/
|
|
129
|
+
async function loadFile(file, metadata) {
|
|
130
|
+
const extension = path.extname(file);
|
|
131
|
+
const content = await (0, promises_1.readFile)(file, {
|
|
132
|
+
encoding: 'utf-8'
|
|
133
|
+
});
|
|
134
|
+
const hash = (0, hash_js_1.sha256)()
|
|
135
|
+
.update(content)
|
|
136
|
+
// Hack to ensure that file hashes are different for different versions of the parser.
|
|
137
|
+
.update(usx_parser_1.PARSER_VERSION)
|
|
138
|
+
.digest('hex');
|
|
139
|
+
return {
|
|
140
|
+
content,
|
|
141
|
+
metadata: metadata,
|
|
142
|
+
name: file,
|
|
143
|
+
sha256: hash,
|
|
144
|
+
fileType: extension.slice(1),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Defines an uploader that is able to upload files to a directory.
|
|
149
|
+
*/
|
|
150
|
+
class FilesUploader {
|
|
151
|
+
_dir;
|
|
152
|
+
constructor(dir) {
|
|
153
|
+
this._dir = dir;
|
|
154
|
+
}
|
|
155
|
+
get idealBatchSize() {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
async upload(file, overwrite) {
|
|
159
|
+
const filePath = path.resolve(this._dir, makeRelativePath(file.path));
|
|
160
|
+
await (0, promises_1.mkdir)(path.dirname(filePath), { recursive: true });
|
|
161
|
+
if (overwrite || !(0, fs_extra_1.existsSync)(filePath)) {
|
|
162
|
+
await (0, promises_1.writeFile)(filePath, file.content, 'utf-8');
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
exports.FilesUploader = FilesUploader;
|
|
169
|
+
/**
|
|
170
|
+
* Defines an uploader that is able to upload files into a zip file.
|
|
171
|
+
*/
|
|
172
|
+
class ZipUploader {
|
|
173
|
+
_path;
|
|
174
|
+
_initPromise;
|
|
175
|
+
_fileHandle = null;
|
|
176
|
+
_zip = null;
|
|
177
|
+
constructor(filePath) {
|
|
178
|
+
this._path = filePath;
|
|
179
|
+
this._initPromise = this._init();
|
|
180
|
+
}
|
|
181
|
+
async _init() {
|
|
182
|
+
this._fileHandle = await (0, promises_1.open)(path.resolve(this._path), 'w');
|
|
183
|
+
const writableStream = this._fileHandle.createWriteStream();
|
|
184
|
+
this._zip = new zip_js_1.ZipWriter(stream_1.Writable.toWeb(writableStream));
|
|
185
|
+
return this._zip;
|
|
186
|
+
}
|
|
187
|
+
get idealBatchSize() {
|
|
188
|
+
return 50;
|
|
189
|
+
}
|
|
190
|
+
async upload(file, _overwrite) {
|
|
191
|
+
const zip = await this._initPromise;
|
|
192
|
+
let reader;
|
|
193
|
+
if (file.content instanceof stream_1.Readable) {
|
|
194
|
+
reader = stream_1.Readable.toWeb(file.content);
|
|
195
|
+
}
|
|
196
|
+
else if (typeof file.content === 'string') {
|
|
197
|
+
reader = new zip_js_1.TextReader(file.content);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
throw new Error('Unknown file content type');
|
|
201
|
+
}
|
|
202
|
+
await zip.add(trimRelativePath(file.path), reader);
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
async dispose() {
|
|
206
|
+
if (this._zip) {
|
|
207
|
+
await this._zip.close();
|
|
208
|
+
}
|
|
209
|
+
if (this._fileHandle) {
|
|
210
|
+
await this._fileHandle.close();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
exports.ZipUploader = ZipUploader;
|
|
215
|
+
function trimRelativePath(path) {
|
|
216
|
+
if (path.startsWith('./')) {
|
|
217
|
+
return path.substring(2);
|
|
218
|
+
}
|
|
219
|
+
else if (path.startsWith('../')) {
|
|
220
|
+
return path.substring(3);
|
|
221
|
+
}
|
|
222
|
+
else if (path.startsWith('/')) {
|
|
223
|
+
return path.substring(1);
|
|
224
|
+
}
|
|
225
|
+
return path;
|
|
226
|
+
}
|
|
227
|
+
function makeRelativePath(path) {
|
|
228
|
+
if (path.startsWith('/')) {
|
|
229
|
+
return '.' + path;
|
|
230
|
+
}
|
|
231
|
+
return path;
|
|
232
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as db from './db';
|
|
2
|
+
import * as downloads from './downloads';
|
|
3
|
+
import * as uploads from './uploads';
|
|
4
|
+
import * as actions from './actions';
|
|
5
|
+
import * as files from './files';
|
|
6
|
+
import * as s3 from './s3';
|
|
7
|
+
export { db, downloads, uploads, actions, files, s3, };
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.s3 = exports.files = exports.actions = exports.uploads = exports.downloads = exports.db = void 0;
|
|
27
|
+
const db = __importStar(require("./db"));
|
|
28
|
+
exports.db = db;
|
|
29
|
+
const downloads = __importStar(require("./downloads"));
|
|
30
|
+
exports.downloads = downloads;
|
|
31
|
+
const uploads = __importStar(require("./uploads"));
|
|
32
|
+
exports.uploads = uploads;
|
|
33
|
+
const actions = __importStar(require("./actions"));
|
|
34
|
+
exports.actions = actions;
|
|
35
|
+
const files = __importStar(require("./files"));
|
|
36
|
+
exports.files = files;
|
|
37
|
+
const s3 = __importStar(require("./s3"));
|
|
38
|
+
exports.s3 = s3;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "Translation" (
|
|
3
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
4
|
+
"name" TEXT NOT NULL,
|
|
5
|
+
"website" TEXT NOT NULL,
|
|
6
|
+
"licenseUrl" TEXT NOT NULL,
|
|
7
|
+
"shortName" TEXT,
|
|
8
|
+
"englishName" TEXT NOT NULL,
|
|
9
|
+
"language" TEXT NOT NULL,
|
|
10
|
+
"textDirection" TEXT NOT NULL
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
-- CreateTable
|
|
14
|
+
CREATE TABLE "Book" (
|
|
15
|
+
"id" TEXT NOT NULL,
|
|
16
|
+
"translationId" TEXT NOT NULL,
|
|
17
|
+
"name" TEXT NOT NULL,
|
|
18
|
+
"commonName" TEXT NOT NULL,
|
|
19
|
+
"title" TEXT,
|
|
20
|
+
"numberOfChapters" INTEGER NOT NULL,
|
|
21
|
+
|
|
22
|
+
PRIMARY KEY ("translationId", "id"),
|
|
23
|
+
CONSTRAINT "Book_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
-- CreateTable
|
|
27
|
+
CREATE TABLE "Chapter" (
|
|
28
|
+
"number" INTEGER NOT NULL,
|
|
29
|
+
"bookId" TEXT NOT NULL,
|
|
30
|
+
"translationId" TEXT NOT NULL,
|
|
31
|
+
"apiLink" TEXT NOT NULL,
|
|
32
|
+
|
|
33
|
+
PRIMARY KEY ("translationId", "bookId", "number"),
|
|
34
|
+
CONSTRAINT "Chapter_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
35
|
+
CONSTRAINT "Chapter_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
-- CreateTable
|
|
39
|
+
CREATE TABLE "ChapterVerse" (
|
|
40
|
+
"number" INTEGER NOT NULL,
|
|
41
|
+
"chapterNumber" INTEGER NOT NULL,
|
|
42
|
+
"bookId" TEXT NOT NULL,
|
|
43
|
+
"translationId" TEXT NOT NULL,
|
|
44
|
+
"text" TEXT NOT NULL,
|
|
45
|
+
|
|
46
|
+
PRIMARY KEY ("translationId", "bookId", "chapterNumber", "number"),
|
|
47
|
+
CONSTRAINT "ChapterVerse_translationId_bookId_chapterNumber_fkey" FOREIGN KEY ("translationId", "bookId", "chapterNumber") REFERENCES "Chapter" ("translationId", "bookId", "number") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
48
|
+
CONSTRAINT "ChapterVerse_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
49
|
+
CONSTRAINT "ChapterVerse_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
-- CreateTable
|
|
53
|
+
CREATE TABLE "ChapterFootnote" (
|
|
54
|
+
"id" INTEGER NOT NULL,
|
|
55
|
+
"chapterNumber" INTEGER NOT NULL,
|
|
56
|
+
"bookId" TEXT NOT NULL,
|
|
57
|
+
"translationId" TEXT NOT NULL,
|
|
58
|
+
"text" TEXT NOT NULL,
|
|
59
|
+
"verseNumber" INTEGER,
|
|
60
|
+
|
|
61
|
+
PRIMARY KEY ("translationId", "bookId", "chapterNumber", "id"),
|
|
62
|
+
CONSTRAINT "ChapterFootnote_translationId_bookId_chapterNumber_fkey" FOREIGN KEY ("translationId", "bookId", "chapterNumber") REFERENCES "Chapter" ("translationId", "bookId", "number") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
63
|
+
CONSTRAINT "ChapterFootnote_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
64
|
+
CONSTRAINT "ChapterFootnote_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
65
|
+
CONSTRAINT "ChapterFootnote_translationId_bookId_chapterNumber_verseNumber_fkey" FOREIGN KEY ("translationId", "bookId", "chapterNumber", "verseNumber") REFERENCES "ChapterVerse" ("translationId", "bookId", "chapterNumber", "number") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
66
|
+
);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Warnings:
|
|
3
|
+
|
|
4
|
+
- Added the required column `order` to the `Book` table without a default value. This is not possible if the table is not empty.
|
|
5
|
+
|
|
6
|
+
*/
|
|
7
|
+
-- RedefineTables
|
|
8
|
+
PRAGMA defer_foreign_keys=ON;
|
|
9
|
+
PRAGMA foreign_keys=OFF;
|
|
10
|
+
CREATE TABLE "new_Book" (
|
|
11
|
+
"id" TEXT NOT NULL,
|
|
12
|
+
"translationId" TEXT NOT NULL,
|
|
13
|
+
"name" TEXT NOT NULL,
|
|
14
|
+
"commonName" TEXT NOT NULL,
|
|
15
|
+
"title" TEXT,
|
|
16
|
+
"order" INTEGER NOT NULL,
|
|
17
|
+
"numberOfChapters" INTEGER NOT NULL,
|
|
18
|
+
|
|
19
|
+
PRIMARY KEY ("translationId", "id"),
|
|
20
|
+
CONSTRAINT "Book_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
21
|
+
);
|
|
22
|
+
INSERT INTO "new_Book" ("commonName", "id", "name", "numberOfChapters", "title", "translationId") SELECT "commonName", "id", "name", "numberOfChapters", "title", "translationId" FROM "Book";
|
|
23
|
+
DROP TABLE "Book";
|
|
24
|
+
ALTER TABLE "new_Book" RENAME TO "Book";
|
|
25
|
+
PRAGMA foreign_keys=ON;
|
|
26
|
+
PRAGMA defer_foreign_keys=OFF;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Warnings:
|
|
3
|
+
|
|
4
|
+
- Added the required column `contentJson` to the `ChapterVerse` table without a default value. This is not possible if the table is not empty.
|
|
5
|
+
|
|
6
|
+
*/
|
|
7
|
+
-- RedefineTables
|
|
8
|
+
PRAGMA defer_foreign_keys=ON;
|
|
9
|
+
PRAGMA foreign_keys=OFF;
|
|
10
|
+
CREATE TABLE "new_Chapter" (
|
|
11
|
+
"number" INTEGER NOT NULL,
|
|
12
|
+
"bookId" TEXT NOT NULL,
|
|
13
|
+
"translationId" TEXT NOT NULL,
|
|
14
|
+
"apiLink" TEXT NOT NULL,
|
|
15
|
+
"previousChapterTranslationId" TEXT,
|
|
16
|
+
"previousChapterBookId" TEXT,
|
|
17
|
+
"previousChapterNumber" INTEGER,
|
|
18
|
+
|
|
19
|
+
PRIMARY KEY ("translationId", "bookId", "number"),
|
|
20
|
+
CONSTRAINT "Chapter_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
21
|
+
CONSTRAINT "Chapter_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
22
|
+
CONSTRAINT "Chapter_previousChapterTranslationId_previousChapterBookId_previousChapterNumber_fkey" FOREIGN KEY ("previousChapterTranslationId", "previousChapterBookId", "previousChapterNumber") REFERENCES "Chapter" ("translationId", "bookId", "number") ON DELETE SET NULL ON UPDATE CASCADE
|
|
23
|
+
);
|
|
24
|
+
INSERT INTO "new_Chapter" ("apiLink", "bookId", "number", "translationId") SELECT "apiLink", "bookId", "number", "translationId" FROM "Chapter";
|
|
25
|
+
DROP TABLE "Chapter";
|
|
26
|
+
ALTER TABLE "new_Chapter" RENAME TO "Chapter";
|
|
27
|
+
CREATE UNIQUE INDEX "Chapter_previousChapterTranslationId_previousChapterBookId_previousChapterNumber_key" ON "Chapter"("previousChapterTranslationId", "previousChapterBookId", "previousChapterNumber");
|
|
28
|
+
CREATE TABLE "new_ChapterVerse" (
|
|
29
|
+
"number" INTEGER NOT NULL,
|
|
30
|
+
"chapterNumber" INTEGER NOT NULL,
|
|
31
|
+
"bookId" TEXT NOT NULL,
|
|
32
|
+
"translationId" TEXT NOT NULL,
|
|
33
|
+
"text" TEXT NOT NULL,
|
|
34
|
+
"contentJson" TEXT NOT NULL,
|
|
35
|
+
|
|
36
|
+
PRIMARY KEY ("translationId", "bookId", "chapterNumber", "number"),
|
|
37
|
+
CONSTRAINT "ChapterVerse_translationId_bookId_chapterNumber_fkey" FOREIGN KEY ("translationId", "bookId", "chapterNumber") REFERENCES "Chapter" ("translationId", "bookId", "number") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
38
|
+
CONSTRAINT "ChapterVerse_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
39
|
+
CONSTRAINT "ChapterVerse_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
40
|
+
);
|
|
41
|
+
INSERT INTO "new_ChapterVerse" ("bookId", "chapterNumber", "number", "text", "translationId") SELECT "bookId", "chapterNumber", "number", "text", "translationId" FROM "ChapterVerse";
|
|
42
|
+
DROP TABLE "ChapterVerse";
|
|
43
|
+
ALTER TABLE "new_ChapterVerse" RENAME TO "ChapterVerse";
|
|
44
|
+
PRAGMA foreign_keys=ON;
|
|
45
|
+
PRAGMA defer_foreign_keys=OFF;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Warnings:
|
|
3
|
+
|
|
4
|
+
- Added the required column `json` to the `Chapter` table without a default value. This is not possible if the table is not empty.
|
|
5
|
+
|
|
6
|
+
*/
|
|
7
|
+
-- RedefineTables
|
|
8
|
+
PRAGMA defer_foreign_keys=ON;
|
|
9
|
+
PRAGMA foreign_keys=OFF;
|
|
10
|
+
CREATE TABLE "new_Chapter" (
|
|
11
|
+
"number" INTEGER NOT NULL,
|
|
12
|
+
"bookId" TEXT NOT NULL,
|
|
13
|
+
"translationId" TEXT NOT NULL,
|
|
14
|
+
"apiLink" TEXT NOT NULL,
|
|
15
|
+
"json" TEXT NOT NULL,
|
|
16
|
+
"previousChapterTranslationId" TEXT,
|
|
17
|
+
"previousChapterBookId" TEXT,
|
|
18
|
+
"previousChapterNumber" INTEGER,
|
|
19
|
+
|
|
20
|
+
PRIMARY KEY ("translationId", "bookId", "number"),
|
|
21
|
+
CONSTRAINT "Chapter_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
22
|
+
CONSTRAINT "Chapter_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
23
|
+
CONSTRAINT "Chapter_previousChapterTranslationId_previousChapterBookId_previousChapterNumber_fkey" FOREIGN KEY ("previousChapterTranslationId", "previousChapterBookId", "previousChapterNumber") REFERENCES "Chapter" ("translationId", "bookId", "number") ON DELETE SET NULL ON UPDATE CASCADE
|
|
24
|
+
);
|
|
25
|
+
INSERT INTO "new_Chapter" ("apiLink", "bookId", "number", "previousChapterBookId", "previousChapterNumber", "previousChapterTranslationId", "translationId") SELECT "apiLink", "bookId", "number", "previousChapterBookId", "previousChapterNumber", "previousChapterTranslationId", "translationId" FROM "Chapter";
|
|
26
|
+
DROP TABLE "Chapter";
|
|
27
|
+
ALTER TABLE "new_Chapter" RENAME TO "Chapter";
|
|
28
|
+
CREATE UNIQUE INDEX "Chapter_previousChapterTranslationId_previousChapterBookId_previousChapterNumber_key" ON "Chapter"("previousChapterTranslationId", "previousChapterBookId", "previousChapterNumber");
|
|
29
|
+
PRAGMA foreign_keys=ON;
|
|
30
|
+
PRAGMA defer_foreign_keys=OFF;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Warnings:
|
|
3
|
+
|
|
4
|
+
- You are about to drop the column `apiLink` on the `Chapter` table. All the data in the column will be lost.
|
|
5
|
+
- You are about to drop the column `previousChapterBookId` on the `Chapter` table. All the data in the column will be lost.
|
|
6
|
+
- You are about to drop the column `previousChapterNumber` on the `Chapter` table. All the data in the column will be lost.
|
|
7
|
+
- You are about to drop the column `previousChapterTranslationId` on the `Chapter` table. All the data in the column will be lost.
|
|
8
|
+
|
|
9
|
+
*/
|
|
10
|
+
-- RedefineTables
|
|
11
|
+
PRAGMA defer_foreign_keys=ON;
|
|
12
|
+
PRAGMA foreign_keys=OFF;
|
|
13
|
+
CREATE TABLE "new_Chapter" (
|
|
14
|
+
"number" INTEGER NOT NULL,
|
|
15
|
+
"bookId" TEXT NOT NULL,
|
|
16
|
+
"translationId" TEXT NOT NULL,
|
|
17
|
+
"json" TEXT NOT NULL,
|
|
18
|
+
|
|
19
|
+
PRIMARY KEY ("translationId", "bookId", "number"),
|
|
20
|
+
CONSTRAINT "Chapter_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
21
|
+
CONSTRAINT "Chapter_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
22
|
+
);
|
|
23
|
+
INSERT INTO "new_Chapter" ("bookId", "json", "number", "translationId") SELECT "bookId", "json", "number", "translationId" FROM "Chapter";
|
|
24
|
+
DROP TABLE "Chapter";
|
|
25
|
+
ALTER TABLE "new_Chapter" RENAME TO "Chapter";
|
|
26
|
+
PRAGMA foreign_keys=ON;
|
|
27
|
+
PRAGMA defer_foreign_keys=OFF;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- CreateTable
|
|
2
|
+
CREATE TABLE "ChapterAudioUrl" (
|
|
3
|
+
"number" INTEGER NOT NULL,
|
|
4
|
+
"bookId" TEXT NOT NULL,
|
|
5
|
+
"translationId" TEXT NOT NULL,
|
|
6
|
+
"reader" TEXT NOT NULL,
|
|
7
|
+
"url" TEXT NOT NULL,
|
|
8
|
+
|
|
9
|
+
PRIMARY KEY ("translationId", "bookId", "number", "reader"),
|
|
10
|
+
CONSTRAINT "ChapterAudioUrl_translationId_bookId_fkey" FOREIGN KEY ("translationId", "bookId") REFERENCES "Book" ("translationId", "id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
11
|
+
CONSTRAINT "ChapterAudioUrl_translationId_fkey" FOREIGN KEY ("translationId") REFERENCES "Translation" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
|
12
|
+
CONSTRAINT "ChapterAudioUrl_translationId_bookId_number_fkey" FOREIGN KEY ("translationId", "bookId", "number") REFERENCES "Chapter" ("translationId", "bookId", "number") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
13
|
+
);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
-- AlterTable
|
|
2
|
+
ALTER TABLE "Book" ADD COLUMN "sha256" TEXT;
|
|
3
|
+
|
|
4
|
+
-- AlterTable
|
|
5
|
+
ALTER TABLE "Chapter" ADD COLUMN "sha256" TEXT;
|
|
6
|
+
|
|
7
|
+
-- AlterTable
|
|
8
|
+
ALTER TABLE "ChapterFootnote" ADD COLUMN "sha256" TEXT;
|
|
9
|
+
|
|
10
|
+
-- AlterTable
|
|
11
|
+
ALTER TABLE "ChapterVerse" ADD COLUMN "sha256" TEXT;
|
|
12
|
+
|
|
13
|
+
-- AlterTable
|
|
14
|
+
ALTER TABLE "Translation" ADD COLUMN "sha256" TEXT;
|
|
15
|
+
|
|
16
|
+
-- CreateTable
|
|
17
|
+
CREATE TABLE "InputFile" (
|
|
18
|
+
"translationId" TEXT NOT NULL,
|
|
19
|
+
"name" TEXT NOT NULL,
|
|
20
|
+
"format" TEXT NOT NULL,
|
|
21
|
+
"sha256" TEXT NOT NULL,
|
|
22
|
+
"sizeInBytes" INTEGER NOT NULL,
|
|
23
|
+
|
|
24
|
+
PRIMARY KEY ("translationId", "name")
|
|
25
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023, Gildas Lormeau
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|