shamela 1.2.3 → 1.3.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/LICENSE.MD +1 -1
- package/README.md +262 -6
- package/dist/index.d.ts +208 -115
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/package.json +22 -13
package/LICENSE.MD
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright 2024 Ragaeeb Haq>
|
|
1
|
+
Copyright 2024-2025 Ragaeeb Haq>
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
4
|
|
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://wakatime.com/badge/user/a0b906ce-b8e7-4463-8bce-383238df6d4b/project/faef70ab-efdb-448b-ab83-0fc66c95888e)
|
|
4
4
|
[](https://github.com/ragaeeb/shamela/actions/workflows/e2e.yml)
|
|
5
|
+
[](https://shamela.vercel.app)
|
|
5
6
|
[](https://github.com/ragaeeb/shamela/actions/workflows/build.yml) 
|
|
6
7
|

|
|
7
8
|
[](https://codecov.io/gh/ragaeeb/shamela)
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|

|
|
13
14
|

|
|
14
15
|
|
|
15
|
-
A
|
|
16
|
+
A universal TypeScript library for accessing and downloading Maktabah Shamela v4 APIs. The package runs in both Node.js and modern browsers, providing ergonomic helpers to interact with the Shamela API, download master and book databases, and retrieve book data programmatically.
|
|
16
17
|
|
|
17
18
|
## Table of Contents
|
|
18
19
|
|
|
@@ -20,19 +21,23 @@ A `Node.js` library for accessing and downloading Maktabah Shamela v4 APIs. This
|
|
|
20
21
|
- [Environment Variables](#environment-variables)
|
|
21
22
|
- [Usage](#usage)
|
|
22
23
|
- [Getting Started](#getting-started)
|
|
24
|
+
- [Next.js / Bundled Environments](#nextjs--bundled-environments)
|
|
23
25
|
- [API Functions](#api-functions)
|
|
24
26
|
- [getMasterMetadata](#getmastermetadata)
|
|
25
27
|
- [downloadMasterDatabase](#downloadmasterdatabase)
|
|
26
28
|
- [getBookMetadata](#getbookmetadata)
|
|
27
29
|
- [downloadBook](#downloadbook)
|
|
28
30
|
- [getBook](#getbook)
|
|
31
|
+
- [getMaster](#getmaster)
|
|
29
32
|
- [getCoverUrl](#getcoverurl)
|
|
30
33
|
- [Examples](#examples)
|
|
31
34
|
- [Downloading the Master Database](#downloading-the-master-database)
|
|
32
35
|
- [Downloading a Book](#downloading-a-book)
|
|
33
36
|
- [Retrieving Book Data](#retrieving-book-data)
|
|
34
|
-
- [
|
|
37
|
+
- [Retrieving Master Data in memory](#retrieving-master-data-in-memory)
|
|
35
38
|
- [Data Structures](#data-structures)
|
|
39
|
+
- [Next.js demo](#nextjs-demo)
|
|
40
|
+
- [Troubleshooting](#troubleshooting)
|
|
36
41
|
- [Testing](#testing)
|
|
37
42
|
- [License](#license)
|
|
38
43
|
|
|
@@ -67,6 +72,7 @@ Before using the library, you need to set up some environment variables for API
|
|
|
67
72
|
- `SHAMELA_API_KEY`: Your API key for accessing the Shamela API.
|
|
68
73
|
- `SHAMELA_API_MASTER_PATCH_ENDPOINT`: The endpoint URL for the master database patches.
|
|
69
74
|
- `SHAMELA_API_BOOKS_ENDPOINT`: The base endpoint URL for book-related API calls.
|
|
75
|
+
- `SHAMELA_SQLJS_WASM_URL` (optional): Override the default CDN URL used to load the `sql.js` WebAssembly binary when running in the browser.
|
|
70
76
|
|
|
71
77
|
You can set these variables in a `.env` file at the root of your project:
|
|
72
78
|
|
|
@@ -74,8 +80,34 @@ You can set these variables in a `.env` file at the root of your project:
|
|
|
74
80
|
SHAMELA_API_KEY=your_api_key_here
|
|
75
81
|
SHAMELA_API_MASTER_PATCH_ENDPOINT=https://shamela.ws/api/master_patch
|
|
76
82
|
SHAMELA_API_BOOKS_ENDPOINT=https://shamela.ws/api/books
|
|
83
|
+
# Optional when you host sql-wasm.wasm yourself
|
|
84
|
+
# SHAMELA_SQLJS_WASM_URL=https://example.com/sql-wasm.wasm
|
|
77
85
|
```
|
|
78
86
|
|
|
87
|
+
### Runtime configuration (browsers and serverless)
|
|
88
|
+
|
|
89
|
+
When you cannot rely on environment variables—such as when running inside a browser, an edge worker, or a serverless function—use the `configure` helper to provide credentials at runtime:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { configure } from 'shamela';
|
|
93
|
+
|
|
94
|
+
configure({
|
|
95
|
+
apiKey: process.env.NEXT_PUBLIC_SHAMELA_KEY,
|
|
96
|
+
booksEndpoint: 'https://shamela.ws/api/books',
|
|
97
|
+
masterPatchEndpoint: 'https://shamela.ws/api/master_patch',
|
|
98
|
+
// Optional: host sql-wasm.wasm yourself to control caching/CDN placement
|
|
99
|
+
sqlJsWasmUrl: '/assets/sql-wasm.wasm',
|
|
100
|
+
// Optional: integrate with your application's logging system
|
|
101
|
+
logger: console,
|
|
102
|
+
// Optional: provide a custom fetch implementation (for tests or SSR)
|
|
103
|
+
fetchImplementation: fetch,
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
You can call `configure` multiple times—values are merged, so later calls update only the keys you pass in.
|
|
108
|
+
|
|
109
|
+
The optional `logger` must expose `debug`, `info`, `warn`, and `error` methods. When omitted, the library stays silent by default.
|
|
110
|
+
|
|
79
111
|
## Usage
|
|
80
112
|
|
|
81
113
|
### Getting Started
|
|
@@ -89,10 +121,92 @@ import {
|
|
|
89
121
|
getBookMetadata,
|
|
90
122
|
downloadBook,
|
|
91
123
|
getBook,
|
|
124
|
+
getMaster,
|
|
92
125
|
getCoverUrl,
|
|
93
126
|
} from 'shamela';
|
|
94
127
|
```
|
|
95
128
|
|
|
129
|
+
### Next.js / Bundled Environments
|
|
130
|
+
|
|
131
|
+
When using this library in Next.js or other bundled environments (webpack/Turbopack), you need some additional configuration to ensure the sql.js WASM file is loaded correctly.
|
|
132
|
+
|
|
133
|
+
#### 1. Update your Next.js configuration
|
|
134
|
+
|
|
135
|
+
Add the following to your `next.config.js` or `next.config.ts`:
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import type { NextConfig } from 'next';
|
|
139
|
+
|
|
140
|
+
const nextConfig: NextConfig = {
|
|
141
|
+
experimental: {
|
|
142
|
+
serverComponentsExternalPackages: ['shamela', 'sql.js'],
|
|
143
|
+
},
|
|
144
|
+
serverExternalPackages: ['shamela', 'sql.js'],
|
|
145
|
+
// ... rest of your config
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export default nextConfig;
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
This tells Next.js to exclude these packages from bundling and load them directly from `node_modules`.
|
|
152
|
+
|
|
153
|
+
#### 2. Create a server-only configuration file
|
|
154
|
+
|
|
155
|
+
Create a configuration file that will be imported only in server-side code:
|
|
156
|
+
|
|
157
|
+
**Option A: Using the `createNodeConfig` helper (Recommended)**
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// lib/shamela-server.ts
|
|
161
|
+
import { configure, createNodeConfig } from 'shamela';
|
|
162
|
+
|
|
163
|
+
// Configure once when this module loads
|
|
164
|
+
configure(createNodeConfig({
|
|
165
|
+
apiKey: process.env.SHAMELA_API_KEY,
|
|
166
|
+
booksEndpoint: process.env.SHAMELA_BOOKS_ENDPOINT,
|
|
167
|
+
masterPatchEndpoint: process.env.SHAMELA_MASTER_ENDPOINT,
|
|
168
|
+
}));
|
|
169
|
+
|
|
170
|
+
// Re-export the functions you need
|
|
171
|
+
export { getBookMetadata, downloadBook, getMaster, getBook } from 'shamela';
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Option B: Manual configuration**
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
// lib/shamela-server.ts
|
|
178
|
+
import { configure } from 'shamela';
|
|
179
|
+
import { join } from 'node:path';
|
|
180
|
+
|
|
181
|
+
configure({
|
|
182
|
+
sqlJsWasmUrl: join(process.cwd(), 'node_modules', 'sql.js', 'dist', 'sql-wasm.wasm'),
|
|
183
|
+
apiKey: process.env.SHAMELA_API_KEY,
|
|
184
|
+
booksEndpoint: process.env.SHAMELA_BOOKS_ENDPOINT,
|
|
185
|
+
masterPatchEndpoint: process.env.SHAMELA_MASTER_ENDPOINT,
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
export { getBookMetadata, downloadBook, getMaster, getBook } from 'shamela';
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### 3. Use in Server Actions or API Routes
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
'use server';
|
|
195
|
+
|
|
196
|
+
import { getBookMetadata, downloadBook } from '@/lib/shamela-server';
|
|
197
|
+
|
|
198
|
+
export async function downloadBookAction(bookId: number) {
|
|
199
|
+
const metadata = await getBookMetadata(bookId);
|
|
200
|
+
const result = await downloadBook(bookId, {
|
|
201
|
+
bookMetadata: metadata,
|
|
202
|
+
outputFile: { path: `./books/${bookId}.db` }
|
|
203
|
+
});
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Important:** Never import `shamela` directly in your `layout.tsx` or client components. Only use it in server-side code (Server Actions, API Routes, or Server Components).
|
|
209
|
+
|
|
96
210
|
### API Functions
|
|
97
211
|
|
|
98
212
|
#### getMasterMetadata
|
|
@@ -239,6 +353,26 @@ console.log(bookData.titles?.length); // Number of title entries
|
|
|
239
353
|
console.log(bookData.pages[0].content); // Content of the first page
|
|
240
354
|
```
|
|
241
355
|
|
|
356
|
+
#### getMaster
|
|
357
|
+
|
|
358
|
+
Retrieves the entire master dataset (authors, books, categories) as a JavaScript object, including the version number that the
|
|
359
|
+
API reports for the snapshot.
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
getMaster(): Promise<MasterData>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Returns:** Promise that resolves to the complete master dataset with version metadata
|
|
366
|
+
|
|
367
|
+
**Example:**
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
const masterData = await getMaster();
|
|
371
|
+
console.log(masterData.version); // Version of the downloaded master database
|
|
372
|
+
console.log(masterData.books.length); // Number of books available
|
|
373
|
+
console.log(masterData.categories.length); // Number of categories available
|
|
374
|
+
```
|
|
375
|
+
|
|
242
376
|
#### getCoverUrl
|
|
243
377
|
|
|
244
378
|
Generates the URL for a book's cover image.
|
|
@@ -278,6 +412,7 @@ import { downloadMasterDatabase } from 'shamela';
|
|
|
278
412
|
outputFile: { path: './shamela_master.json' },
|
|
279
413
|
});
|
|
280
414
|
console.log(`Master data exported to: ${jsonPath}`);
|
|
415
|
+
console.log('The JSON file includes authors, books, categories, and the master version number.');
|
|
281
416
|
} catch (error) {
|
|
282
417
|
console.error('Error downloading master database:', error);
|
|
283
418
|
}
|
|
@@ -339,6 +474,24 @@ import { getBook } from 'shamela';
|
|
|
339
474
|
})();
|
|
340
475
|
```
|
|
341
476
|
|
|
477
|
+
### Retrieving Master Data in memory
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
import { getMaster } from 'shamela';
|
|
481
|
+
|
|
482
|
+
(async () => {
|
|
483
|
+
try {
|
|
484
|
+
const masterData = await getMaster();
|
|
485
|
+
|
|
486
|
+
console.log(`Master snapshot version: ${masterData.version}`);
|
|
487
|
+
console.log(`Master dataset includes ${masterData.books.length} books`);
|
|
488
|
+
console.log(`Master dataset includes ${masterData.categories.length} categories`);
|
|
489
|
+
} catch (error) {
|
|
490
|
+
console.error('Error retrieving master data:', error);
|
|
491
|
+
}
|
|
492
|
+
})();
|
|
493
|
+
```
|
|
494
|
+
|
|
342
495
|
### Getting Book Cover URLs
|
|
343
496
|
|
|
344
497
|
```javascript
|
|
@@ -379,6 +532,7 @@ The library provides comprehensive TypeScript types for all data structures:
|
|
|
379
532
|
- `authors`: Raw entries from the `author` table with the original `biography`, `death_text`, `death_number`, `is_deleted`, and `name` fields.
|
|
380
533
|
- `books`: Raw entries from the `book` table containing the original metadata columns (`author`, `bibliography`, `category`, `date`, `hint`, `major_release`, `metadata`, `minor_release`, `pdf_links`, `printed`, `type`, and `is_deleted`).
|
|
381
534
|
- `categories`: Raw entries from the `category` table including `is_deleted`, `order`, and `name`.
|
|
535
|
+
- `version`: Version number reported by the Shamela API for the downloaded master database.
|
|
382
536
|
|
|
383
537
|
### Page
|
|
384
538
|
|
|
@@ -401,12 +555,112 @@ The library provides comprehensive TypeScript types for all data structures:
|
|
|
401
555
|
- `parseContentRobust(content: string)`: Converts Shamela page HTML into a list of structured lines while preserving title markers and punctuation.
|
|
402
556
|
- `sanitizePageContent(content: string)`: Removes common footnote markers and normalises ligatures from Shamela pages.
|
|
403
557
|
|
|
558
|
+
## Next.js demo
|
|
559
|
+
|
|
560
|
+
A minimal Next.js 16 application in `demo/` replaces the previous Storybook setup and offers an RTL-friendly explorer for the Shamela APIs. The server renders requests so the browser can bypass CORS limits and you only need to provide an API key and book identifier at runtime.
|
|
561
|
+
|
|
562
|
+
Create a `demo/.env.local` file (or export the variables in your shell) containing the real endpoints you wish to call:
|
|
563
|
+
|
|
564
|
+
```dotenv
|
|
565
|
+
SHAMELA_API_MASTER_PATCH_ENDPOINT=https://dev.shamela.ws/api/v1/patches/master
|
|
566
|
+
SHAMELA_API_BOOKS_ENDPOINT=https://dev.shamela.ws/api/v1/patches/book-updates
|
|
567
|
+
# Optional when hosting the wasm asset yourself
|
|
568
|
+
# SHAMELA_SQLJS_WASM_URL=https://example.com/sql-wasm.wasm
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
Then launch the demo:
|
|
572
|
+
|
|
573
|
+
```bash
|
|
574
|
+
bun run demo
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
Visit [http://localhost:3000](http://localhost:3000) to enter your API key, choose a book ID, and call helpers like `getMasterMetadata`, `getMaster`, `getBook`, and `downloadMasterDatabase` directly from the interface. For production-style builds use:
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
bun run demo:build
|
|
581
|
+
bun run demo:start
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
When deploying to Vercel, point the project to the `demo` directory and supply the same environment variables in the dashboard so the API routes can reach Shamela.
|
|
585
|
+
|
|
586
|
+
## Troubleshooting
|
|
587
|
+
|
|
588
|
+
### Error: "Unable to locate sql-wasm.wasm file"
|
|
589
|
+
|
|
590
|
+
This error occurs when the library cannot automatically find the WASM file. This is common in bundled environments like Next.js with Turbopack/Webpack.
|
|
591
|
+
|
|
592
|
+
**Solution:** Use the `createNodeConfig` helper or explicitly configure `sqlJsWasmUrl`:
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
import { configure, createNodeConfig } from 'shamela';
|
|
596
|
+
|
|
597
|
+
// Option 1: Use the helper (recommended)
|
|
598
|
+
configure(createNodeConfig({
|
|
599
|
+
apiKey: process.env.SHAMELA_API_KEY,
|
|
600
|
+
booksEndpoint: process.env.SHAMELA_BOOKS_ENDPOINT,
|
|
601
|
+
masterPatchEndpoint: process.env.SHAMELA_MASTER_ENDPOINT,
|
|
602
|
+
}));
|
|
603
|
+
|
|
604
|
+
// Option 2: Manual configuration
|
|
605
|
+
import { join } from 'node:path';
|
|
606
|
+
|
|
607
|
+
configure({
|
|
608
|
+
sqlJsWasmUrl: join(process.cwd(), 'node_modules', 'sql.js', 'dist', 'sql-wasm.wasm'),
|
|
609
|
+
apiKey: process.env.SHAMELA_API_KEY,
|
|
610
|
+
// ... other config
|
|
611
|
+
});
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
### Error: "ENOENT: no such file or directory, open 'https://...'"
|
|
615
|
+
|
|
616
|
+
This means you're in a Node.js environment but providing an HTTPS URL for the WASM file. Node.js requires a filesystem path, not a URL.
|
|
617
|
+
|
|
618
|
+
**Solution:** Use a filesystem path instead of a URL:
|
|
619
|
+
|
|
620
|
+
```typescript
|
|
621
|
+
// ❌ Wrong - HTTPS URL in Node.js
|
|
622
|
+
configure({
|
|
623
|
+
sqlJsWasmUrl: 'https://cdn.jsdelivr.net/npm/sql.js@1.13.0/dist/sql-wasm.wasm'
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
// ✅ Correct - Filesystem path or use createNodeConfig
|
|
627
|
+
import { createNodeConfig } from 'shamela';
|
|
628
|
+
|
|
629
|
+
configure(createNodeConfig({
|
|
630
|
+
apiKey: process.env.SHAMELA_API_KEY,
|
|
631
|
+
// ... other config
|
|
632
|
+
}));
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### Next.js: Module not found errors during build
|
|
636
|
+
|
|
637
|
+
If you see webpack/Turbopack errors about not being able to resolve modules during the build phase:
|
|
638
|
+
|
|
639
|
+
1. Make sure you've added `serverExternalPackages` to your `next.config.js` (see [Next.js / Bundled Environments](#nextjs--bundled-environments))
|
|
640
|
+
2. Ensure you're only importing shamela in server-side code (Server Actions, API Routes, Server Components)
|
|
641
|
+
3. Never import shamela in `layout.tsx` or client components
|
|
642
|
+
4. Create a separate `lib/shamela-server.ts` file for configuration
|
|
643
|
+
|
|
644
|
+
### Double `node_modules/node_modules` path error
|
|
645
|
+
|
|
646
|
+
If you see paths like `/path/to/project/node_modules/node_modules/sql.js/...`, this indicates the library's auto-detection failed due to bundling. Use explicit configuration:
|
|
647
|
+
|
|
648
|
+
```typescript
|
|
649
|
+
import { configure, createNodeConfig } from 'shamela';
|
|
650
|
+
|
|
651
|
+
configure(createNodeConfig({
|
|
652
|
+
apiKey: process.env.SHAMELA_API_KEY,
|
|
653
|
+
booksEndpoint: process.env.SHAMELA_BOOKS_ENDPOINT,
|
|
654
|
+
masterPatchEndpoint: process.env.SHAMELA_MASTER_ENDPOINT,
|
|
655
|
+
}));
|
|
656
|
+
```
|
|
657
|
+
|
|
404
658
|
## Testing
|
|
405
659
|
|
|
406
|
-
The library includes comprehensive tests
|
|
660
|
+
The library includes comprehensive tests powered by `bun test`. To run the unit suite, ensure you have the necessary environment variables set, then execute:
|
|
407
661
|
|
|
408
662
|
```bash
|
|
409
|
-
bun test
|
|
663
|
+
bun test src
|
|
410
664
|
```
|
|
411
665
|
|
|
412
666
|
For end-to-end tests:
|
|
@@ -415,10 +669,12 @@ For end-to-end tests:
|
|
|
415
669
|
bun run e2e
|
|
416
670
|
```
|
|
417
671
|
|
|
418
|
-
|
|
672
|
+
### Formatting
|
|
673
|
+
|
|
674
|
+
Apply Biome formatting across the repository with:
|
|
419
675
|
|
|
420
676
|
```bash
|
|
421
|
-
bun run
|
|
677
|
+
bun run format
|
|
422
678
|
```
|
|
423
679
|
|
|
424
680
|
## License
|