@helloao/cli 0.0.5 → 0.0.6

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/schema.prisma CHANGED
@@ -1,154 +1,154 @@
1
- datasource db {
2
- provider = "sqlite"
3
- url = "file:../../bible-api.dev.db"
4
- }
5
-
6
- generator client {
7
- provider = "prisma-client-js"
8
- output = "./prisma-gen"
9
- }
10
-
11
- model Translation {
12
- id String @id
13
- name String
14
- website String
15
- licenseUrl String
16
- shortName String?
17
- englishName String
18
- language String
19
- textDirection String
20
-
21
- // The SHA-256 hash of the translation
22
- // includes everything about the translation, including the books, chapters, verses, footnotes, etc.
23
- sha256 String?
24
-
25
- books Book[]
26
- chapters Chapter[]
27
- verses ChapterVerse[]
28
- footnotes ChapterFootnote[]
29
- audioUrls ChapterAudioUrl[]
30
- }
31
-
32
- model InputFile {
33
- // The ID of the translation that the file is for
34
- translationId String
35
-
36
- // The name of the file
37
- name String
38
-
39
- format String
40
-
41
- // The SHA-256 hash of the file
42
- sha256 String
43
-
44
- sizeInBytes Int
45
-
46
- @@id([translationId, name])
47
- }
48
-
49
- model Book {
50
- id String
51
-
52
- translationId String
53
- translation Translation @relation(fields: [translationId], references: [id])
54
-
55
- name String
56
- commonName String
57
- title String?
58
- order Int
59
-
60
- numberOfChapters Int
61
-
62
- // The SHA-256 hash of the book
63
- sha256 String?
64
-
65
- chapters Chapter[]
66
- verses ChapterVerse[]
67
- footnotes ChapterFootnote[]
68
- audioUrls ChapterAudioUrl[]
69
-
70
- @@id([translationId, id])
71
- }
72
-
73
- model Chapter {
74
- number Int
75
-
76
- bookId String
77
- book Book @relation(fields: [translationId, bookId], references: [translationId, id])
78
-
79
- translationId String
80
- translation Translation @relation(fields: [translationId], references: [id])
81
-
82
- json String // The JSON of the chapter
83
-
84
- // The SHA-256 hash of the chapter
85
- sha256 String?
86
-
87
- verses ChapterVerse[]
88
- footnotes ChapterFootnote[]
89
- audioUrls ChapterAudioUrl[]
90
-
91
- @@id([translationId, bookId, number])
92
- }
93
-
94
- model ChapterAudioUrl {
95
- number Int
96
- bookId String
97
- book Book @relation(fields: [translationId, bookId], references: [translationId, id])
98
-
99
- translationId String
100
- translation Translation @relation(fields: [translationId], references: [id])
101
-
102
- chapter Chapter @relation(fields: [translationId, bookId, number], references: [translationId, bookId, number])
103
-
104
- reader String
105
- url String
106
-
107
- @@id([translationId, bookId, number, reader])
108
- }
109
-
110
- model ChapterVerse {
111
- number Int
112
-
113
- chapterNumber Int
114
- chapter Chapter @relation(fields: [translationId, bookId, chapterNumber], references: [translationId, bookId, number])
115
-
116
- bookId String
117
- book Book @relation(fields: [translationId, bookId], references: [translationId, id])
118
-
119
- translationId String
120
- translation Translation @relation(fields: [translationId], references: [id])
121
-
122
- text String // The text of the verse
123
- contentJson String // The JSON of the verse content
124
-
125
- // The SHA-256 hash of the verse
126
- sha256 String?
127
-
128
- footnotes ChapterFootnote[]
129
-
130
- @@id([translationId, bookId, chapterNumber, number])
131
- }
132
-
133
- model ChapterFootnote {
134
- id Int
135
-
136
- chapterNumber Int
137
- chapter Chapter @relation(fields: [translationId, bookId, chapterNumber], references: [translationId, bookId, number])
138
-
139
- bookId String
140
- book Book @relation(fields: [translationId, bookId], references: [translationId, id])
141
-
142
- translationId String
143
- translation Translation @relation(fields: [translationId], references: [id])
144
-
145
- text String
146
-
147
- // The SHA-256 hash of the footnote
148
- sha256 String?
149
-
150
- verseNumber Int?
151
- verse ChapterVerse? @relation(fields: [translationId, bookId, chapterNumber, verseNumber], references: [translationId, bookId, chapterNumber, number])
152
-
153
- @@id([translationId, bookId, chapterNumber, id])
154
- }
1
+ datasource db {
2
+ provider = "sqlite"
3
+ url = "file:../../bible-api.dev.db"
4
+ }
5
+
6
+ generator client {
7
+ provider = "prisma-client-js"
8
+ output = "./prisma-gen"
9
+ }
10
+
11
+ model Translation {
12
+ id String @id
13
+ name String
14
+ website String
15
+ licenseUrl String
16
+ shortName String?
17
+ englishName String
18
+ language String
19
+ textDirection String
20
+
21
+ // The SHA-256 hash of the translation
22
+ // includes everything about the translation, including the books, chapters, verses, footnotes, etc.
23
+ sha256 String?
24
+
25
+ books Book[]
26
+ chapters Chapter[]
27
+ verses ChapterVerse[]
28
+ footnotes ChapterFootnote[]
29
+ audioUrls ChapterAudioUrl[]
30
+ }
31
+
32
+ model InputFile {
33
+ // The ID of the translation that the file is for
34
+ translationId String
35
+
36
+ // The name of the file
37
+ name String
38
+
39
+ format String
40
+
41
+ // The SHA-256 hash of the file
42
+ sha256 String
43
+
44
+ sizeInBytes Int
45
+
46
+ @@id([translationId, name])
47
+ }
48
+
49
+ model Book {
50
+ id String
51
+
52
+ translationId String
53
+ translation Translation @relation(fields: [translationId], references: [id])
54
+
55
+ name String
56
+ commonName String
57
+ title String?
58
+ order Int
59
+
60
+ numberOfChapters Int
61
+
62
+ // The SHA-256 hash of the book
63
+ sha256 String?
64
+
65
+ chapters Chapter[]
66
+ verses ChapterVerse[]
67
+ footnotes ChapterFootnote[]
68
+ audioUrls ChapterAudioUrl[]
69
+
70
+ @@id([translationId, id])
71
+ }
72
+
73
+ model Chapter {
74
+ number Int
75
+
76
+ bookId String
77
+ book Book @relation(fields: [translationId, bookId], references: [translationId, id])
78
+
79
+ translationId String
80
+ translation Translation @relation(fields: [translationId], references: [id])
81
+
82
+ json String // The JSON of the chapter
83
+
84
+ // The SHA-256 hash of the chapter
85
+ sha256 String?
86
+
87
+ verses ChapterVerse[]
88
+ footnotes ChapterFootnote[]
89
+ audioUrls ChapterAudioUrl[]
90
+
91
+ @@id([translationId, bookId, number])
92
+ }
93
+
94
+ model ChapterAudioUrl {
95
+ number Int
96
+ bookId String
97
+ book Book @relation(fields: [translationId, bookId], references: [translationId, id])
98
+
99
+ translationId String
100
+ translation Translation @relation(fields: [translationId], references: [id])
101
+
102
+ chapter Chapter @relation(fields: [translationId, bookId, number], references: [translationId, bookId, number])
103
+
104
+ reader String
105
+ url String
106
+
107
+ @@id([translationId, bookId, number, reader])
108
+ }
109
+
110
+ model ChapterVerse {
111
+ number Int
112
+
113
+ chapterNumber Int
114
+ chapter Chapter @relation(fields: [translationId, bookId, chapterNumber], references: [translationId, bookId, number])
115
+
116
+ bookId String
117
+ book Book @relation(fields: [translationId, bookId], references: [translationId, id])
118
+
119
+ translationId String
120
+ translation Translation @relation(fields: [translationId], references: [id])
121
+
122
+ text String // The text of the verse
123
+ contentJson String // The JSON of the verse content
124
+
125
+ // The SHA-256 hash of the verse
126
+ sha256 String?
127
+
128
+ footnotes ChapterFootnote[]
129
+
130
+ @@id([translationId, bookId, chapterNumber, number])
131
+ }
132
+
133
+ model ChapterFootnote {
134
+ id Int
135
+
136
+ chapterNumber Int
137
+ chapter Chapter @relation(fields: [translationId, bookId, chapterNumber], references: [translationId, bookId, number])
138
+
139
+ bookId String
140
+ book Book @relation(fields: [translationId, bookId], references: [translationId, id])
141
+
142
+ translationId String
143
+ translation Translation @relation(fields: [translationId], references: [id])
144
+
145
+ text String
146
+
147
+ // The SHA-256 hash of the footnote
148
+ sha256 String?
149
+
150
+ verseNumber Int?
151
+ verse ChapterVerse? @relation(fields: [translationId, bookId, chapterNumber, verseNumber], references: [translationId, bookId, chapterNumber, number])
152
+
153
+ @@id([translationId, bookId, chapterNumber, id])
154
+ }
package/uploads.d.ts CHANGED
@@ -1,7 +1,9 @@
1
- import { SerializedFile, Uploader } from "./files";
2
- import { DatasetOutput } from "@helloao/tools/generation/dataset";
3
- import { PrismaClient } from "@prisma/client";
4
- export interface UploadApiFromDatabaseOptions extends UploadApiOptions {
1
+ import { SerializedFile } from './db';
2
+ import { Uploader } from './files';
3
+ import { DatasetOutput } from '@helloao/tools/generation/dataset';
4
+ import { PrismaClient } from './prisma-gen';
5
+ import { GenerateApiOptions } from '@helloao/tools/generation/api';
6
+ export interface UploadApiFromDatabaseOptions extends UploadApiOptions, GenerateApiOptions {
5
7
  /**
6
8
  * The number of files to upload in each batch.
7
9
  */
@@ -29,6 +31,14 @@ export interface UploadApiOptions {
29
31
  * The AWS profile to use for uploading to S3.
30
32
  */
31
33
  profile?: string;
34
+ /**
35
+ * The AWS access key ID to use for uploading to S3.
36
+ */
37
+ accessKeyId?: string;
38
+ /**
39
+ * The AWS secret access key to use for uploading to S3.
40
+ */
41
+ secretAccessKey?: string;
32
42
  /**
33
43
  * Whether to generate API files that use the common name instead of book IDs.
34
44
  */
@@ -55,7 +65,7 @@ export declare function uploadApiFilesFromDatabase(db: PrismaClient, dest: strin
55
65
  * @param options The options to use for the upload.
56
66
  * @param datasets The datasets to generate the API files from.
57
67
  */
58
- export declare function serializeAndUploadDatasets(dest: string, datasets: AsyncIterable<DatasetOutput>, options?: UploadApiOptions): Promise<void>;
68
+ export declare function serializeAndUploadDatasets(dest: string, datasets: AsyncIterable<DatasetOutput>, options?: UploadApiOptions & GenerateApiOptions): Promise<void>;
59
69
  /**
60
70
  * Uploads the given serialized files to the specified destination.
61
71
  * @param dest The destination to upload the API files to. Supported destinations are S3, zip files, and local directories.
package/uploads.js CHANGED
@@ -34,7 +34,9 @@ async function uploadApiFilesFromDatabase(db, dest, options) {
34
34
  if (options.pretty) {
35
35
  console.log('Generating pretty-printed JSON files');
36
36
  }
37
- const pageSize = typeof options.batchSize === 'number' ? options.batchSize : parseInt(options.batchSize);
37
+ const pageSize = typeof options.batchSize === 'number'
38
+ ? options.batchSize
39
+ : parseInt(options.batchSize);
38
40
  await serializeAndUploadDatasets(dest, (0, db_1.loadDatasets)(db, pageSize, options.translations), options);
39
41
  }
40
42
  /**
@@ -66,92 +68,10 @@ async function serializeAndUploadDatasets(dest, datasets, options = {}) {
66
68
  if (options.pretty) {
67
69
  console.log('Generating pretty-printed JSON files');
68
70
  }
69
- let uploader;
70
- if (dest.startsWith('s3://')) {
71
- console.log('Uploading to S3');
72
- // Upload to S3
73
- const url = dest;
74
- const s3Url = (0, s3_1.parseS3Url)(url);
75
- if (!s3Url) {
76
- throw new Error(`Invalid S3 URL: ${url}`);
77
- }
78
- if (!s3Url.bucketName) {
79
- throw new Error(`Invalid S3 URL: ${url}\nUnable to determine bucket name`);
80
- }
81
- uploader = new s3_1.S3Uploader(s3Url.bucketName, s3Url.objectKey, options.profile ?? null);
82
- }
83
- else if (dest.startsWith('console://')) {
84
- console.log('Uploading to console');
85
- uploader = {
86
- idealBatchSize: 50,
87
- async upload(file, _overwrite) {
88
- console.log(file.path);
89
- console.log(file.content);
90
- return true;
91
- }
92
- };
93
- }
94
- else if ((0, path_1.extname)(dest) === '.zip') {
95
- console.log('Writing to zip file:', dest);
96
- uploader = new files_1.ZipUploader(dest);
97
- }
98
- else if (dest) {
99
- console.log('Writing to local directory:', dest);
100
- uploader = new files_1.FilesUploader(dest);
101
- }
102
- else {
103
- console.error('Unsupported destination:', dest);
104
- process.exit(1);
105
- }
106
- try {
107
- for await (let files of (0, db_1.serializeDatasets)(datasets, {
108
- useCommonName: !!options.useCommonName,
109
- generateAudioFiles: !!options.generateAudioFiles,
110
- pretty: !!options.pretty,
111
- })) {
112
- const batchSize = uploader.idealBatchSize ?? files.length;
113
- const totalBatches = Math.ceil(files.length / batchSize);
114
- console.log('Uploading', files.length, 'total files');
115
- console.log('Uploading in batches of', batchSize);
116
- let offset = 0;
117
- let batchNumber = 1;
118
- let batch = files.slice(offset, offset + batchSize);
119
- while (batch.length > 0) {
120
- console.log('Uploading batch', batchNumber, 'of', totalBatches);
121
- let writtenFiles = 0;
122
- const promises = batch.map(async (file) => {
123
- if (filePattern) {
124
- if (!filePattern.test(file.path)) {
125
- console.log('Skipping file:', file.path);
126
- return;
127
- }
128
- }
129
- const isAvailableTranslations = file.path.endsWith('available_translations.json');
130
- const isCommonFile = !isAvailableTranslations;
131
- if (await uploader.upload(file, overwrite || (overwriteCommonFiles && isCommonFile))) {
132
- writtenFiles++;
133
- }
134
- else {
135
- console.warn('File already exists:', file.path);
136
- console.warn('Skipping file');
137
- }
138
- if (file.content instanceof node_stream_1.Readable) {
139
- file.content.destroy();
140
- }
141
- });
142
- await Promise.all(promises);
143
- console.log('Wrote', writtenFiles, 'files');
144
- batchNumber++;
145
- offset += batchSize;
146
- batch = files.slice(offset, offset + batchSize);
147
- }
148
- }
149
- }
150
- finally {
151
- if (uploader && uploader.dispose) {
152
- await uploader.dispose();
153
- }
154
- }
71
+ const files = (0, db_1.serializeDatasets)(datasets, {
72
+ ...options,
73
+ });
74
+ await uploadFiles(dest, options, files);
155
75
  }
156
76
  /**
157
77
  * Uploads the given serialized files to the specified destination.
@@ -172,7 +92,7 @@ async function uploadFiles(dest, options, serializedFiles) {
172
92
  if (!s3Url.bucketName) {
173
93
  throw new Error(`Invalid S3 URL: ${url}\nUnable to determine bucket name`);
174
94
  }
175
- uploader = new s3_1.S3Uploader(s3Url.bucketName, s3Url.objectKey, options.profile ?? null);
95
+ uploader = new s3_1.S3Uploader(s3Url.bucketName, s3Url.objectKey, (0, s3_1.defaultProviderForOptions)(options));
176
96
  }
177
97
  else if (dest.startsWith('console://')) {
178
98
  console.log('Uploading to console');
@@ -182,7 +102,7 @@ async function uploadFiles(dest, options, serializedFiles) {
182
102
  console.log(file.path);
183
103
  console.log(file.content);
184
104
  return true;
185
- }
105
+ },
186
106
  };
187
107
  }
188
108
  else if ((0, path_1.extname)(dest) === '.zip') {