@nakafa/aksara-contracts 0.27.0
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 +185 -0
- package/README.md +73 -0
- package/dist/artifact/integrity.d.ts +29 -0
- package/dist/artifact/integrity.js +54 -0
- package/dist/artifact/limits.d.ts +26 -0
- package/dist/artifact/limits.js +46 -0
- package/dist/artifact/source.d.ts +21 -0
- package/dist/artifact/source.js +24 -0
- package/dist/artifact/spec.d.ts +148 -0
- package/dist/artifact/spec.js +92 -0
- package/dist/artifact/verify.d.ts +26 -0
- package/dist/artifact/verify.js +18 -0
- package/dist/cache/content.d.ts +52 -0
- package/dist/cache/content.js +80 -0
- package/dist/content.d.ts +168 -0
- package/dist/content.js +107 -0
- package/dist/country.d.ts +4 -0
- package/dist/country.js +8 -0
- package/dist/date.d.ts +24 -0
- package/dist/date.js +44 -0
- package/dist/decode.d.ts +4 -0
- package/dist/decode.js +8 -0
- package/dist/delivery.d.ts +4 -0
- package/dist/delivery.js +7 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.js +8 -0
- package/dist/graph/family.d.ts +45 -0
- package/dist/graph/family.js +85 -0
- package/dist/graph/identity.d.ts +19 -0
- package/dist/graph/identity.js +39 -0
- package/dist/graph/spec.d.ts +20 -0
- package/dist/graph/spec.js +26 -0
- package/dist/hash/text.d.ts +10 -0
- package/dist/hash/text.js +20 -0
- package/dist/ids.d.ts +27 -0
- package/dist/ids.js +63 -0
- package/dist/limits.d.ts +10 -0
- package/dist/limits.js +10 -0
- package/dist/locale.d.ts +37 -0
- package/dist/locale.js +53 -0
- package/dist/material/domain.d.ts +4 -0
- package/dist/material/domain.js +8 -0
- package/dist/preview/artifact.d.ts +198 -0
- package/dist/preview/artifact.js +20 -0
- package/dist/preview/auth.d.ts +71 -0
- package/dist/preview/auth.js +49 -0
- package/dist/preview/document.d.ts +692 -0
- package/dist/preview/document.js +90 -0
- package/dist/preview/spec.d.ts +2517 -0
- package/dist/preview/spec.js +142 -0
- package/dist/preview/target.d.ts +172 -0
- package/dist/preview/target.js +70 -0
- package/dist/program/curriculum.d.ts +69 -0
- package/dist/program/curriculum.js +181 -0
- package/dist/program/snapshot/digest.d.ts +26 -0
- package/dist/program/snapshot/digest.js +220 -0
- package/dist/program/snapshot/hash.d.ts +31 -0
- package/dist/program/snapshot/hash.js +40 -0
- package/dist/program/snapshot/row-hash.d.ts +155 -0
- package/dist/program/snapshot/row-hash.js +34 -0
- package/dist/program/snapshot/row.d.ts +139 -0
- package/dist/program/snapshot/row.js +28 -0
- package/dist/program/snapshot/spec.d.ts +36 -0
- package/dist/program/snapshot/spec.js +39 -0
- package/dist/program/spec.d.ts +85 -0
- package/dist/program/spec.js +197 -0
- package/dist/projection/article.d.ts +145 -0
- package/dist/projection/article.js +150 -0
- package/dist/projection/digest.d.ts +261 -0
- package/dist/projection/digest.js +59 -0
- package/dist/projection/hash.d.ts +3 -0
- package/dist/projection/hash.js +10 -0
- package/dist/projection/material.d.ts +109 -0
- package/dist/projection/material.js +160 -0
- package/dist/projection/page.d.ts +112 -0
- package/dist/projection/page.js +106 -0
- package/dist/projection/question.d.ts +520 -0
- package/dist/projection/question.js +109 -0
- package/dist/projection/spec.d.ts +503 -0
- package/dist/projection/spec.js +56 -0
- package/dist/projection/verify.d.ts +281 -0
- package/dist/projection/verify.js +86 -0
- package/dist/question/identity.d.ts +175 -0
- package/dist/question/identity.js +205 -0
- package/dist/question/item.d.ts +453 -0
- package/dist/question/item.js +146 -0
- package/dist/question/response.d.ts +175 -0
- package/dist/question/response.js +150 -0
- package/dist/quran/attribution.d.ts +48 -0
- package/dist/quran/attribution.js +44 -0
- package/dist/quran/identity.d.ts +105 -0
- package/dist/quran/identity.js +100 -0
- package/dist/quran/notes.d.ts +56 -0
- package/dist/quran/notes.js +142 -0
- package/dist/quran/provenance.d.ts +257 -0
- package/dist/quran/provenance.js +144 -0
- package/dist/quran/snapshot/digest.d.ts +33 -0
- package/dist/quran/snapshot/digest.js +232 -0
- package/dist/quran/snapshot/hash.d.ts +51 -0
- package/dist/quran/snapshot/hash.js +50 -0
- package/dist/quran/snapshot/row/hash.d.ts +748 -0
- package/dist/quran/snapshot/row/hash.js +115 -0
- package/dist/quran/snapshot/row.d.ts +354 -0
- package/dist/quran/snapshot/row.js +91 -0
- package/dist/quran/snapshot/spec.d.ts +50 -0
- package/dist/quran/snapshot/spec.js +66 -0
- package/dist/quran/source.d.ts +206 -0
- package/dist/quran/source.js +153 -0
- package/dist/quran/spec.d.ts +47 -0
- package/dist/quran/spec.js +41 -0
- package/dist/quran/text.d.ts +7 -0
- package/dist/quran/text.js +11 -0
- package/dist/release/canonical.d.ts +23 -0
- package/dist/release/canonical.js +29 -0
- package/dist/release/current/evidence.d.ts +424 -0
- package/dist/release/current/evidence.js +41 -0
- package/dist/release/current/runtime.d.ts +4 -0
- package/dist/release/current/runtime.js +15 -0
- package/dist/release/current/state.d.ts +567 -0
- package/dist/release/current/state.js +91 -0
- package/dist/release/digest.d.ts +54 -0
- package/dist/release/digest.js +71 -0
- package/dist/release/hash.d.ts +72 -0
- package/dist/release/hash.js +14 -0
- package/dist/release/head.d.ts +206 -0
- package/dist/release/head.js +131 -0
- package/dist/release/items.d.ts +98 -0
- package/dist/release/items.js +114 -0
- package/dist/release/lifecycle.d.ts +297 -0
- package/dist/release/lifecycle.js +97 -0
- package/dist/release/origin.d.ts +30 -0
- package/dist/release/origin.js +24 -0
- package/dist/release/policy.d.ts +45 -0
- package/dist/release/policy.js +124 -0
- package/dist/release/result/digest.d.ts +127 -0
- package/dist/release/result/digest.js +140 -0
- package/dist/release/result/spec.d.ts +4 -0
- package/dist/release/result/spec.js +5 -0
- package/dist/release/rollback/digest.d.ts +126 -0
- package/dist/release/rollback/digest.js +92 -0
- package/dist/release/rollback/spec.d.ts +1729 -0
- package/dist/release/rollback/spec.js +156 -0
- package/dist/release/route/digest.d.ts +45 -0
- package/dist/release/route/digest.js +59 -0
- package/dist/release/route/page.d.ts +56 -0
- package/dist/release/route/page.js +46 -0
- package/dist/release/route/spec.d.ts +49 -0
- package/dist/release/route/spec.js +40 -0
- package/dist/release/route/verify.d.ts +66 -0
- package/dist/release/route/verify.js +67 -0
- package/dist/release/signing.d.ts +6 -0
- package/dist/release/signing.js +38 -0
- package/dist/release/snapshot/data.d.ts +475 -0
- package/dist/release/snapshot/data.js +74 -0
- package/dist/release/snapshot/evidence-requirement.d.ts +22 -0
- package/dist/release/snapshot/evidence-requirement.js +21 -0
- package/dist/release/snapshot/evidence.d.ts +58 -0
- package/dist/release/snapshot/evidence.js +14 -0
- package/dist/release/snapshot/program-evidence.d.ts +17 -0
- package/dist/release/snapshot/program-evidence.js +39 -0
- package/dist/release/snapshot/quran-evidence.d.ts +27 -0
- package/dist/release/snapshot/quran-evidence.js +43 -0
- package/dist/release/snapshot/scope.d.ts +60 -0
- package/dist/release/snapshot/scope.js +102 -0
- package/dist/release/snapshot/spec.d.ts +193 -0
- package/dist/release/snapshot/spec.js +139 -0
- package/dist/release/snapshot/tryout-evidence.d.ts +22 -0
- package/dist/release/snapshot/tryout-evidence.js +86 -0
- package/dist/release/snapshot/verify.d.ts +710 -0
- package/dist/release/snapshot/verify.js +147 -0
- package/dist/release/spec.d.ts +491 -0
- package/dist/release/spec.js +200 -0
- package/dist/release/verify.d.ts +98 -0
- package/dist/release/verify.js +70 -0
- package/dist/renderer/compatibility.d.ts +35 -0
- package/dist/renderer/compatibility.js +48 -0
- package/dist/renderer/component.d.ts +99 -0
- package/dist/renderer/component.js +102 -0
- package/dist/renderer/contract.d.ts +144 -0
- package/dist/renderer/contract.js +122 -0
- package/dist/renderer/domain.d.ts +6 -0
- package/dist/renderer/domain.js +18 -0
- package/dist/renderer/manifest.d.ts +86 -0
- package/dist/renderer/manifest.js +49 -0
- package/dist/renderer/selection.d.ts +39 -0
- package/dist/renderer/selection.js +87 -0
- package/dist/runtime/error.d.ts +8 -0
- package/dist/runtime/error.js +20 -0
- package/dist/runtime/protected/limits.d.ts +10 -0
- package/dist/runtime/protected/limits.js +15 -0
- package/dist/runtime/protected/spec.d.ts +328 -0
- package/dist/runtime/protected/spec.js +79 -0
- package/dist/runtime/protected/verify.d.ts +97 -0
- package/dist/runtime/protected/verify.js +72 -0
- package/dist/runtime/result.d.ts +12 -0
- package/dist/runtime/result.js +17 -0
- package/dist/runtime/spec.d.ts +705 -0
- package/dist/runtime/spec.js +61 -0
- package/dist/runtime/verify.d.ts +479 -0
- package/dist/runtime/verify.js +123 -0
- package/dist/signature/spec.d.ts +53 -0
- package/dist/signature/spec.js +29 -0
- package/dist/signature/trusted.d.ts +19 -0
- package/dist/signature/trusted.js +32 -0
- package/dist/signature/verify.d.ts +10 -0
- package/dist/signature/verify.js +82 -0
- package/dist/text/order.d.ts +2 -0
- package/dist/text/order.js +10 -0
- package/dist/text/syntax.d.ts +6 -0
- package/dist/text/syntax.js +15 -0
- package/dist/transport/batch.d.ts +971 -0
- package/dist/transport/batch.js +101 -0
- package/dist/transport/failure.d.ts +168 -0
- package/dist/transport/failure.js +194 -0
- package/dist/transport/group.d.ts +2946 -0
- package/dist/transport/group.js +47 -0
- package/dist/transport/limits.d.ts +30 -0
- package/dist/transport/limits.js +30 -0
- package/dist/transport/request.d.ts +9333 -0
- package/dist/transport/request.js +121 -0
- package/dist/transport/response.d.ts +6247 -0
- package/dist/transport/response.js +181 -0
- package/dist/transport/runtime.d.ts +77 -0
- package/dist/transport/runtime.js +33 -0
- package/dist/transport/snapshot.d.ts +978 -0
- package/dist/transport/snapshot.js +70 -0
- package/dist/tryout/canonical.d.ts +2 -0
- package/dist/tryout/canonical.js +11 -0
- package/dist/tryout/catalog-hash.d.ts +134 -0
- package/dist/tryout/catalog-hash.js +203 -0
- package/dist/tryout/catalog.d.ts +376 -0
- package/dist/tryout/catalog.js +147 -0
- package/dist/tryout/content-hash.d.ts +89 -0
- package/dist/tryout/content-hash.js +72 -0
- package/dist/tryout/identity.d.ts +12 -0
- package/dist/tryout/identity.js +46 -0
- package/dist/tryout/key.d.ts +4 -0
- package/dist/tryout/key.js +8 -0
- package/dist/tryout/language.d.ts +24 -0
- package/dist/tryout/language.js +32 -0
- package/dist/tryout/locale-closure.d.ts +20 -0
- package/dist/tryout/locale-closure.js +164 -0
- package/dist/tryout/placement-closure.d.ts +5 -0
- package/dist/tryout/placement-closure.js +30 -0
- package/dist/tryout/placement-hash.d.ts +11 -0
- package/dist/tryout/placement-hash.js +55 -0
- package/dist/tryout/placement.d.ts +280 -0
- package/dist/tryout/placement.js +82 -0
- package/dist/tryout/row-hash.d.ts +28 -0
- package/dist/tryout/row-hash.js +50 -0
- package/dist/tryout/runtime/canonical.d.ts +8 -0
- package/dist/tryout/runtime/canonical.js +33 -0
- package/dist/tryout/runtime/hash.d.ts +32 -0
- package/dist/tryout/runtime/hash.js +11 -0
- package/dist/tryout/runtime/source.d.ts +42 -0
- package/dist/tryout/runtime/source.js +47 -0
- package/dist/tryout/runtime/spec.d.ts +58 -0
- package/dist/tryout/runtime/spec.js +21 -0
- package/dist/tryout/runtime/verify.d.ts +61 -0
- package/dist/tryout/runtime/verify.js +69 -0
- package/dist/tryout/snapshot/canonical.d.ts +7 -0
- package/dist/tryout/snapshot/canonical.js +17 -0
- package/dist/tryout/snapshot/hash.d.ts +8 -0
- package/dist/tryout/snapshot/hash.js +19 -0
- package/dist/tryout/snapshot/spec.d.ts +46 -0
- package/dist/tryout/snapshot/spec.js +30 -0
- package/dist/tryout/spec.d.ts +13 -0
- package/dist/tryout/spec.js +15 -0
- package/package.json +506 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { Effect, Schema } from "effect";
|
|
3
|
+
import { canonicalizeLearningGraphIdentity } from "#contracts/graph/spec";
|
|
4
|
+
import { Sha256HashSchema } from "#contracts/ids";
|
|
5
|
+
import { canonicalizeQuranAttribution } from "#contracts/quran/attribution";
|
|
6
|
+
import { QuranSnapshotRowSchema, } from "#contracts/quran/snapshot/row";
|
|
7
|
+
const ROW_DOMAIN = "nakafa.aksara.quran-row";
|
|
8
|
+
/** Node could not compute a deterministic Quran row identity. */
|
|
9
|
+
export class QuranRowHashError extends Schema.TaggedError()("QuranRowHashError", { scope: Schema.Literals(["digest", "row"]) }) {
|
|
10
|
+
}
|
|
11
|
+
/** Serializes one published translation list in signed field order. */
|
|
12
|
+
function canonicalizeTranslations(translations) {
|
|
13
|
+
return translations.map((translation) => ({
|
|
14
|
+
appLocale: translation.appLocale,
|
|
15
|
+
value: {
|
|
16
|
+
footnotes: translation.value.footnotes,
|
|
17
|
+
text: translation.value.text,
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
/** Serializes signed Tafsir access without trusting object insertion order. */
|
|
22
|
+
function canonicalizeTafsirAccess(access) {
|
|
23
|
+
return {
|
|
24
|
+
appLocale: access.appLocale,
|
|
25
|
+
kind: access.kind,
|
|
26
|
+
notice: access.notice,
|
|
27
|
+
sourceId: access.sourceId,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Serializes one current runtime verse without insertion-order trust. */
|
|
31
|
+
function canonicalizeVerse(verse) {
|
|
32
|
+
return {
|
|
33
|
+
meta: {
|
|
34
|
+
hizbQuarter: verse.meta.hizbQuarter,
|
|
35
|
+
juz: verse.meta.juz,
|
|
36
|
+
manzil: verse.meta.manzil,
|
|
37
|
+
page: verse.meta.page,
|
|
38
|
+
ruku: verse.meta.ruku,
|
|
39
|
+
sajda: verse.meta.sajda,
|
|
40
|
+
},
|
|
41
|
+
number: {
|
|
42
|
+
inQuran: verse.number.inQuran,
|
|
43
|
+
inSurah: verse.number.inSurah,
|
|
44
|
+
},
|
|
45
|
+
tafsir: verse.tafsir.map((entry) => ({
|
|
46
|
+
appLocale: entry.appLocale,
|
|
47
|
+
footnotes: entry.footnotes,
|
|
48
|
+
text: entry.text,
|
|
49
|
+
})),
|
|
50
|
+
text: { arabic: verse.text.arabic },
|
|
51
|
+
translations: canonicalizeTranslations(verse.translations),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Produces stable JSON for one exhaustive current Quran payload. */
|
|
55
|
+
export function canonicalizeQuranRow(payload) {
|
|
56
|
+
if (payload.kind === "quran-attribution") {
|
|
57
|
+
return JSON.stringify({
|
|
58
|
+
activeAppLocales: payload.activeAppLocales,
|
|
59
|
+
kind: payload.kind,
|
|
60
|
+
sources: payload.sources.map(canonicalizeQuranAttribution),
|
|
61
|
+
tafsirAccess: payload.tafsirAccess.map(canonicalizeTafsirAccess),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (payload.kind === "quran-surah") {
|
|
65
|
+
return JSON.stringify({
|
|
66
|
+
kind: payload.kind,
|
|
67
|
+
name: {
|
|
68
|
+
arabic: payload.name.arabic,
|
|
69
|
+
meaning: {
|
|
70
|
+
de: payload.name.meaning.de,
|
|
71
|
+
en: payload.name.meaning.en,
|
|
72
|
+
id: payload.name.meaning.id,
|
|
73
|
+
},
|
|
74
|
+
transliteration: payload.name.transliteration,
|
|
75
|
+
},
|
|
76
|
+
number: payload.number,
|
|
77
|
+
numberOfVerses: payload.numberOfVerses,
|
|
78
|
+
revelation: {
|
|
79
|
+
order: payload.revelation.order,
|
|
80
|
+
place: payload.revelation.place,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (payload.kind === "quran-chunk") {
|
|
85
|
+
return JSON.stringify({
|
|
86
|
+
firstQuranNumber: payload.firstQuranNumber,
|
|
87
|
+
firstVerse: payload.firstVerse,
|
|
88
|
+
kind: payload.kind,
|
|
89
|
+
lastVerse: payload.lastVerse,
|
|
90
|
+
surahNumber: payload.surahNumber,
|
|
91
|
+
verses: payload.verses.map(canonicalizeVerse),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return JSON.stringify({
|
|
95
|
+
appLocale: payload.appLocale,
|
|
96
|
+
graph: canonicalizeLearningGraphIdentity(payload.graph),
|
|
97
|
+
kind: payload.kind,
|
|
98
|
+
route: payload.route,
|
|
99
|
+
surahNumber: payload.surahNumber,
|
|
100
|
+
text: payload.text,
|
|
101
|
+
title: payload.title,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/** Computes one current row's domain-separated identity. */
|
|
105
|
+
export const hashQuranRow = Effect.fn("AksaraContracts.hashQuranRow")((payload) => Effect.try({
|
|
106
|
+
catch: () => new QuranRowHashError({ scope: "row" }),
|
|
107
|
+
try: () => Sha256HashSchema.make(`sha256:${createHash("sha256")
|
|
108
|
+
.update(`${ROW_DOMAIN}\n${canonicalizeQuranRow(payload)}`)
|
|
109
|
+
.digest("hex")}`),
|
|
110
|
+
}));
|
|
111
|
+
/** Creates one snapshot-bound current row. */
|
|
112
|
+
export const bindQuranRow = Effect.fn("AksaraContracts.bindQuranRow")(function* (snapshotId, payload) {
|
|
113
|
+
const rowHash = yield* hashQuranRow(payload);
|
|
114
|
+
return QuranSnapshotRowSchema.make({ payload, rowHash, snapshotId });
|
|
115
|
+
});
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** One locale-indexed QuranEnc translation. */
|
|
3
|
+
export declare const QuranLocalizedTranslationSchema: Schema.Struct<{
|
|
4
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
5
|
+
readonly value: Schema.Struct<{
|
|
6
|
+
readonly footnotes: Schema.String;
|
|
7
|
+
readonly text: Schema.String;
|
|
8
|
+
}>;
|
|
9
|
+
}>;
|
|
10
|
+
export type QuranLocalizedTranslation = typeof QuranLocalizedTranslationSchema.Type;
|
|
11
|
+
/** One exact verse with explicit translation locale entries. */
|
|
12
|
+
export declare const QuranRuntimeVerseSchema: Schema.Struct<{
|
|
13
|
+
readonly meta: Schema.Struct<{
|
|
14
|
+
readonly hizbQuarter: Schema.Int;
|
|
15
|
+
readonly juz: Schema.Int;
|
|
16
|
+
readonly manzil: Schema.Int;
|
|
17
|
+
readonly page: Schema.Int;
|
|
18
|
+
readonly ruku: Schema.Int;
|
|
19
|
+
readonly sajda: Schema.NullOr<Schema.Literals<readonly ["obligatory", "recommended"]>>;
|
|
20
|
+
}>;
|
|
21
|
+
readonly number: Schema.Struct<{
|
|
22
|
+
readonly inQuran: Schema.Int;
|
|
23
|
+
readonly inSurah: Schema.Int;
|
|
24
|
+
}>;
|
|
25
|
+
readonly tafsir: Schema.$Array<Schema.Struct<{
|
|
26
|
+
readonly appLocale: Schema.Literal<"id">;
|
|
27
|
+
readonly footnotes: Schema.NullOr<Schema.String>;
|
|
28
|
+
readonly text: Schema.String;
|
|
29
|
+
}>>;
|
|
30
|
+
readonly text: Schema.Struct<{
|
|
31
|
+
readonly arabic: Schema.String;
|
|
32
|
+
}>;
|
|
33
|
+
readonly translations: Schema.NonEmptyArray<Schema.Struct<{
|
|
34
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
35
|
+
readonly value: Schema.Struct<{
|
|
36
|
+
readonly footnotes: Schema.String;
|
|
37
|
+
readonly text: Schema.String;
|
|
38
|
+
}>;
|
|
39
|
+
}>>;
|
|
40
|
+
}>;
|
|
41
|
+
export type QuranRuntimeVerse = typeof QuranRuntimeVerseSchema.Type;
|
|
42
|
+
/** Immutable bounded runtime row containing ordered verses. */
|
|
43
|
+
export declare const QuranChunkRowSchema: Schema.Struct<{
|
|
44
|
+
readonly firstQuranNumber: Schema.Int;
|
|
45
|
+
readonly firstVerse: Schema.Int;
|
|
46
|
+
readonly kind: Schema.Literal<"quran-chunk">;
|
|
47
|
+
readonly lastVerse: Schema.Int;
|
|
48
|
+
readonly surahNumber: Schema.Int;
|
|
49
|
+
readonly verses: Schema.NonEmptyArray<Schema.Struct<{
|
|
50
|
+
readonly meta: Schema.Struct<{
|
|
51
|
+
readonly hizbQuarter: Schema.Int;
|
|
52
|
+
readonly juz: Schema.Int;
|
|
53
|
+
readonly manzil: Schema.Int;
|
|
54
|
+
readonly page: Schema.Int;
|
|
55
|
+
readonly ruku: Schema.Int;
|
|
56
|
+
readonly sajda: Schema.NullOr<Schema.Literals<readonly ["obligatory", "recommended"]>>;
|
|
57
|
+
}>;
|
|
58
|
+
readonly number: Schema.Struct<{
|
|
59
|
+
readonly inQuran: Schema.Int;
|
|
60
|
+
readonly inSurah: Schema.Int;
|
|
61
|
+
}>;
|
|
62
|
+
readonly tafsir: Schema.$Array<Schema.Struct<{
|
|
63
|
+
readonly appLocale: Schema.Literal<"id">;
|
|
64
|
+
readonly footnotes: Schema.NullOr<Schema.String>;
|
|
65
|
+
readonly text: Schema.String;
|
|
66
|
+
}>>;
|
|
67
|
+
readonly text: Schema.Struct<{
|
|
68
|
+
readonly arabic: Schema.String;
|
|
69
|
+
}>;
|
|
70
|
+
readonly translations: Schema.NonEmptyArray<Schema.Struct<{
|
|
71
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
72
|
+
readonly value: Schema.Struct<{
|
|
73
|
+
readonly footnotes: Schema.String;
|
|
74
|
+
readonly text: Schema.String;
|
|
75
|
+
}>;
|
|
76
|
+
}>>;
|
|
77
|
+
}>>;
|
|
78
|
+
}>;
|
|
79
|
+
/** One locale-specific Quran route and full-text search document. */
|
|
80
|
+
export declare const QuranSearchRowSchema: Schema.Struct<{
|
|
81
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
82
|
+
readonly graph: Schema.Struct<{
|
|
83
|
+
readonly alignmentId: Schema.String;
|
|
84
|
+
readonly assetId: Schema.String;
|
|
85
|
+
readonly conceptId: Schema.String;
|
|
86
|
+
readonly learningObjectId: Schema.String;
|
|
87
|
+
readonly lensId: Schema.String;
|
|
88
|
+
}>;
|
|
89
|
+
readonly kind: Schema.Literal<"quran-search">;
|
|
90
|
+
readonly route: Schema.brand<Schema.String, "@NakafaAI/AksaraPublicPath">;
|
|
91
|
+
readonly surahNumber: Schema.Int;
|
|
92
|
+
readonly text: Schema.String;
|
|
93
|
+
readonly title: Schema.String;
|
|
94
|
+
}>;
|
|
95
|
+
/** Complete structured Quran row vocabulary. */
|
|
96
|
+
export declare const QuranRowPayloadSchema: Schema.Union<readonly [Schema.Struct<{
|
|
97
|
+
readonly activeAppLocales: Schema.NonEmptyArray<Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">>;
|
|
98
|
+
readonly kind: Schema.Literal<"quran-attribution">;
|
|
99
|
+
readonly sources: Schema.NonEmptyArray<Schema.Union<readonly [Schema.Struct<{
|
|
100
|
+
readonly copy: Schema.NonEmptyArray<Schema.Struct<{
|
|
101
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
102
|
+
readonly notice: Schema.Trimmed;
|
|
103
|
+
readonly title: Schema.Trimmed;
|
|
104
|
+
}>>;
|
|
105
|
+
readonly publisher: Schema.Trimmed;
|
|
106
|
+
readonly retrievedAt: Schema.String;
|
|
107
|
+
readonly sourceUrl: Schema.String;
|
|
108
|
+
readonly updateUrl: Schema.String;
|
|
109
|
+
readonly version: Schema.Trimmed;
|
|
110
|
+
readonly artifact: Schema.Struct<{
|
|
111
|
+
readonly byteCount: Schema.Int;
|
|
112
|
+
readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
113
|
+
readonly fileCount: Schema.Int;
|
|
114
|
+
}>;
|
|
115
|
+
readonly id: Schema.Literals<readonly ["tanzil-text", "tanzil-metadata", "kemenag-names", "bubenheim-names", "quranenc-english", "quranenc-indonesian", "quranenc-german", "quranenc-tafsir"]>;
|
|
116
|
+
readonly kind: Schema.Literal<"embedded">;
|
|
117
|
+
readonly terms: Schema.Struct<{
|
|
118
|
+
readonly artifact: Schema.Struct<{
|
|
119
|
+
readonly byteCount: Schema.Int;
|
|
120
|
+
readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
121
|
+
readonly fileCount: Schema.Int;
|
|
122
|
+
}>;
|
|
123
|
+
readonly url: Schema.String;
|
|
124
|
+
}>;
|
|
125
|
+
}>, Schema.Struct<{
|
|
126
|
+
readonly copy: Schema.NonEmptyArray<Schema.Struct<{
|
|
127
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
128
|
+
readonly notice: Schema.Trimmed;
|
|
129
|
+
readonly title: Schema.Trimmed;
|
|
130
|
+
}>>;
|
|
131
|
+
readonly publisher: Schema.Trimmed;
|
|
132
|
+
readonly retrievedAt: Schema.String;
|
|
133
|
+
readonly sourceUrl: Schema.String;
|
|
134
|
+
readonly updateUrl: Schema.String;
|
|
135
|
+
readonly version: Schema.Trimmed;
|
|
136
|
+
readonly id: Schema.Literals<readonly ["mokhtasar-english", "mokhtasar-german"]>;
|
|
137
|
+
readonly kind: Schema.Literal<"external">;
|
|
138
|
+
readonly terms: Schema.Struct<{
|
|
139
|
+
readonly access: Schema.Literal<"link-only">;
|
|
140
|
+
readonly url: Schema.String;
|
|
141
|
+
}>;
|
|
142
|
+
}>]>>;
|
|
143
|
+
readonly tafsirAccess: Schema.NonEmptyArray<Schema.Union<readonly [Schema.Struct<{
|
|
144
|
+
readonly appLocale: Schema.brand<Schema.Literal<"en">, "@NakafaAI/AksaraAppLocale">;
|
|
145
|
+
readonly kind: Schema.Literal<"external">;
|
|
146
|
+
readonly notice: Schema.Trimmed;
|
|
147
|
+
readonly sourceId: Schema.Literal<"mokhtasar-english">;
|
|
148
|
+
}>, Schema.Struct<{
|
|
149
|
+
readonly appLocale: Schema.brand<Schema.Literal<"id">, "@NakafaAI/AksaraAppLocale">;
|
|
150
|
+
readonly kind: Schema.Literal<"embedded">;
|
|
151
|
+
readonly notice: Schema.Trimmed;
|
|
152
|
+
readonly sourceId: Schema.Literal<"quranenc-tafsir">;
|
|
153
|
+
}>, Schema.Struct<{
|
|
154
|
+
readonly appLocale: Schema.brand<Schema.Literal<"de">, "@NakafaAI/AksaraAppLocale">;
|
|
155
|
+
readonly kind: Schema.Literal<"external">;
|
|
156
|
+
readonly notice: Schema.Trimmed;
|
|
157
|
+
readonly sourceId: Schema.Literal<"mokhtasar-german">;
|
|
158
|
+
}>]>>;
|
|
159
|
+
}>, Schema.Struct<{
|
|
160
|
+
readonly name: Schema.Struct<{
|
|
161
|
+
readonly arabic: Schema.String;
|
|
162
|
+
readonly meaning: Schema.$Record<Schema.Literals<readonly ["en", "id", "de"]>, Schema.String>;
|
|
163
|
+
readonly transliteration: Schema.String;
|
|
164
|
+
}>;
|
|
165
|
+
readonly number: Schema.Int;
|
|
166
|
+
readonly numberOfVerses: Schema.Int;
|
|
167
|
+
readonly revelation: Schema.Struct<{
|
|
168
|
+
readonly order: Schema.Int;
|
|
169
|
+
readonly place: Schema.Literals<readonly ["Meccan", "Medinan"]>;
|
|
170
|
+
}>;
|
|
171
|
+
readonly kind: Schema.Literal<"quran-surah">;
|
|
172
|
+
}>, Schema.Struct<{
|
|
173
|
+
readonly firstQuranNumber: Schema.Int;
|
|
174
|
+
readonly firstVerse: Schema.Int;
|
|
175
|
+
readonly kind: Schema.Literal<"quran-chunk">;
|
|
176
|
+
readonly lastVerse: Schema.Int;
|
|
177
|
+
readonly surahNumber: Schema.Int;
|
|
178
|
+
readonly verses: Schema.NonEmptyArray<Schema.Struct<{
|
|
179
|
+
readonly meta: Schema.Struct<{
|
|
180
|
+
readonly hizbQuarter: Schema.Int;
|
|
181
|
+
readonly juz: Schema.Int;
|
|
182
|
+
readonly manzil: Schema.Int;
|
|
183
|
+
readonly page: Schema.Int;
|
|
184
|
+
readonly ruku: Schema.Int;
|
|
185
|
+
readonly sajda: Schema.NullOr<Schema.Literals<readonly ["obligatory", "recommended"]>>;
|
|
186
|
+
}>;
|
|
187
|
+
readonly number: Schema.Struct<{
|
|
188
|
+
readonly inQuran: Schema.Int;
|
|
189
|
+
readonly inSurah: Schema.Int;
|
|
190
|
+
}>;
|
|
191
|
+
readonly tafsir: Schema.$Array<Schema.Struct<{
|
|
192
|
+
readonly appLocale: Schema.Literal<"id">;
|
|
193
|
+
readonly footnotes: Schema.NullOr<Schema.String>;
|
|
194
|
+
readonly text: Schema.String;
|
|
195
|
+
}>>;
|
|
196
|
+
readonly text: Schema.Struct<{
|
|
197
|
+
readonly arabic: Schema.String;
|
|
198
|
+
}>;
|
|
199
|
+
readonly translations: Schema.NonEmptyArray<Schema.Struct<{
|
|
200
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
201
|
+
readonly value: Schema.Struct<{
|
|
202
|
+
readonly footnotes: Schema.String;
|
|
203
|
+
readonly text: Schema.String;
|
|
204
|
+
}>;
|
|
205
|
+
}>>;
|
|
206
|
+
}>>;
|
|
207
|
+
}>, Schema.Struct<{
|
|
208
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
209
|
+
readonly graph: Schema.Struct<{
|
|
210
|
+
readonly alignmentId: Schema.String;
|
|
211
|
+
readonly assetId: Schema.String;
|
|
212
|
+
readonly conceptId: Schema.String;
|
|
213
|
+
readonly learningObjectId: Schema.String;
|
|
214
|
+
readonly lensId: Schema.String;
|
|
215
|
+
}>;
|
|
216
|
+
readonly kind: Schema.Literal<"quran-search">;
|
|
217
|
+
readonly route: Schema.brand<Schema.String, "@NakafaAI/AksaraPublicPath">;
|
|
218
|
+
readonly surahNumber: Schema.Int;
|
|
219
|
+
readonly text: Schema.String;
|
|
220
|
+
readonly title: Schema.String;
|
|
221
|
+
}>]>;
|
|
222
|
+
export type QuranRowPayload = typeof QuranRowPayloadSchema.Type;
|
|
223
|
+
/** One content-addressed row bound to an immutable Quran snapshot. */
|
|
224
|
+
export declare const QuranSnapshotRowSchema: Schema.Struct<{
|
|
225
|
+
readonly payload: Schema.Union<readonly [Schema.Struct<{
|
|
226
|
+
readonly activeAppLocales: Schema.NonEmptyArray<Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">>;
|
|
227
|
+
readonly kind: Schema.Literal<"quran-attribution">;
|
|
228
|
+
readonly sources: Schema.NonEmptyArray<Schema.Union<readonly [Schema.Struct<{
|
|
229
|
+
readonly copy: Schema.NonEmptyArray<Schema.Struct<{
|
|
230
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
231
|
+
readonly notice: Schema.Trimmed;
|
|
232
|
+
readonly title: Schema.Trimmed;
|
|
233
|
+
}>>;
|
|
234
|
+
readonly publisher: Schema.Trimmed;
|
|
235
|
+
readonly retrievedAt: Schema.String;
|
|
236
|
+
readonly sourceUrl: Schema.String;
|
|
237
|
+
readonly updateUrl: Schema.String;
|
|
238
|
+
readonly version: Schema.Trimmed;
|
|
239
|
+
readonly artifact: Schema.Struct<{
|
|
240
|
+
readonly byteCount: Schema.Int;
|
|
241
|
+
readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
242
|
+
readonly fileCount: Schema.Int;
|
|
243
|
+
}>;
|
|
244
|
+
readonly id: Schema.Literals<readonly ["tanzil-text", "tanzil-metadata", "kemenag-names", "bubenheim-names", "quranenc-english", "quranenc-indonesian", "quranenc-german", "quranenc-tafsir"]>;
|
|
245
|
+
readonly kind: Schema.Literal<"embedded">;
|
|
246
|
+
readonly terms: Schema.Struct<{
|
|
247
|
+
readonly artifact: Schema.Struct<{
|
|
248
|
+
readonly byteCount: Schema.Int;
|
|
249
|
+
readonly digest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
250
|
+
readonly fileCount: Schema.Int;
|
|
251
|
+
}>;
|
|
252
|
+
readonly url: Schema.String;
|
|
253
|
+
}>;
|
|
254
|
+
}>, Schema.Struct<{
|
|
255
|
+
readonly copy: Schema.NonEmptyArray<Schema.Struct<{
|
|
256
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
257
|
+
readonly notice: Schema.Trimmed;
|
|
258
|
+
readonly title: Schema.Trimmed;
|
|
259
|
+
}>>;
|
|
260
|
+
readonly publisher: Schema.Trimmed;
|
|
261
|
+
readonly retrievedAt: Schema.String;
|
|
262
|
+
readonly sourceUrl: Schema.String;
|
|
263
|
+
readonly updateUrl: Schema.String;
|
|
264
|
+
readonly version: Schema.Trimmed;
|
|
265
|
+
readonly id: Schema.Literals<readonly ["mokhtasar-english", "mokhtasar-german"]>;
|
|
266
|
+
readonly kind: Schema.Literal<"external">;
|
|
267
|
+
readonly terms: Schema.Struct<{
|
|
268
|
+
readonly access: Schema.Literal<"link-only">;
|
|
269
|
+
readonly url: Schema.String;
|
|
270
|
+
}>;
|
|
271
|
+
}>]>>;
|
|
272
|
+
readonly tafsirAccess: Schema.NonEmptyArray<Schema.Union<readonly [Schema.Struct<{
|
|
273
|
+
readonly appLocale: Schema.brand<Schema.Literal<"en">, "@NakafaAI/AksaraAppLocale">;
|
|
274
|
+
readonly kind: Schema.Literal<"external">;
|
|
275
|
+
readonly notice: Schema.Trimmed;
|
|
276
|
+
readonly sourceId: Schema.Literal<"mokhtasar-english">;
|
|
277
|
+
}>, Schema.Struct<{
|
|
278
|
+
readonly appLocale: Schema.brand<Schema.Literal<"id">, "@NakafaAI/AksaraAppLocale">;
|
|
279
|
+
readonly kind: Schema.Literal<"embedded">;
|
|
280
|
+
readonly notice: Schema.Trimmed;
|
|
281
|
+
readonly sourceId: Schema.Literal<"quranenc-tafsir">;
|
|
282
|
+
}>, Schema.Struct<{
|
|
283
|
+
readonly appLocale: Schema.brand<Schema.Literal<"de">, "@NakafaAI/AksaraAppLocale">;
|
|
284
|
+
readonly kind: Schema.Literal<"external">;
|
|
285
|
+
readonly notice: Schema.Trimmed;
|
|
286
|
+
readonly sourceId: Schema.Literal<"mokhtasar-german">;
|
|
287
|
+
}>]>>;
|
|
288
|
+
}>, Schema.Struct<{
|
|
289
|
+
readonly name: Schema.Struct<{
|
|
290
|
+
readonly arabic: Schema.String;
|
|
291
|
+
readonly meaning: Schema.$Record<Schema.Literals<readonly ["en", "id", "de"]>, Schema.String>;
|
|
292
|
+
readonly transliteration: Schema.String;
|
|
293
|
+
}>;
|
|
294
|
+
readonly number: Schema.Int;
|
|
295
|
+
readonly numberOfVerses: Schema.Int;
|
|
296
|
+
readonly revelation: Schema.Struct<{
|
|
297
|
+
readonly order: Schema.Int;
|
|
298
|
+
readonly place: Schema.Literals<readonly ["Meccan", "Medinan"]>;
|
|
299
|
+
}>;
|
|
300
|
+
readonly kind: Schema.Literal<"quran-surah">;
|
|
301
|
+
}>, Schema.Struct<{
|
|
302
|
+
readonly firstQuranNumber: Schema.Int;
|
|
303
|
+
readonly firstVerse: Schema.Int;
|
|
304
|
+
readonly kind: Schema.Literal<"quran-chunk">;
|
|
305
|
+
readonly lastVerse: Schema.Int;
|
|
306
|
+
readonly surahNumber: Schema.Int;
|
|
307
|
+
readonly verses: Schema.NonEmptyArray<Schema.Struct<{
|
|
308
|
+
readonly meta: Schema.Struct<{
|
|
309
|
+
readonly hizbQuarter: Schema.Int;
|
|
310
|
+
readonly juz: Schema.Int;
|
|
311
|
+
readonly manzil: Schema.Int;
|
|
312
|
+
readonly page: Schema.Int;
|
|
313
|
+
readonly ruku: Schema.Int;
|
|
314
|
+
readonly sajda: Schema.NullOr<Schema.Literals<readonly ["obligatory", "recommended"]>>;
|
|
315
|
+
}>;
|
|
316
|
+
readonly number: Schema.Struct<{
|
|
317
|
+
readonly inQuran: Schema.Int;
|
|
318
|
+
readonly inSurah: Schema.Int;
|
|
319
|
+
}>;
|
|
320
|
+
readonly tafsir: Schema.$Array<Schema.Struct<{
|
|
321
|
+
readonly appLocale: Schema.Literal<"id">;
|
|
322
|
+
readonly footnotes: Schema.NullOr<Schema.String>;
|
|
323
|
+
readonly text: Schema.String;
|
|
324
|
+
}>>;
|
|
325
|
+
readonly text: Schema.Struct<{
|
|
326
|
+
readonly arabic: Schema.String;
|
|
327
|
+
}>;
|
|
328
|
+
readonly translations: Schema.NonEmptyArray<Schema.Struct<{
|
|
329
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
330
|
+
readonly value: Schema.Struct<{
|
|
331
|
+
readonly footnotes: Schema.String;
|
|
332
|
+
readonly text: Schema.String;
|
|
333
|
+
}>;
|
|
334
|
+
}>>;
|
|
335
|
+
}>>;
|
|
336
|
+
}>, Schema.Struct<{
|
|
337
|
+
readonly appLocale: Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">;
|
|
338
|
+
readonly graph: Schema.Struct<{
|
|
339
|
+
readonly alignmentId: Schema.String;
|
|
340
|
+
readonly assetId: Schema.String;
|
|
341
|
+
readonly conceptId: Schema.String;
|
|
342
|
+
readonly learningObjectId: Schema.String;
|
|
343
|
+
readonly lensId: Schema.String;
|
|
344
|
+
}>;
|
|
345
|
+
readonly kind: Schema.Literal<"quran-search">;
|
|
346
|
+
readonly route: Schema.brand<Schema.String, "@NakafaAI/AksaraPublicPath">;
|
|
347
|
+
readonly surahNumber: Schema.Int;
|
|
348
|
+
readonly text: Schema.String;
|
|
349
|
+
readonly title: Schema.String;
|
|
350
|
+
}>]>;
|
|
351
|
+
readonly rowHash: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
352
|
+
readonly snapshotId: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
353
|
+
}>;
|
|
354
|
+
export type QuranSnapshotRow = typeof QuranSnapshotRowSchema.Type;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { LearningGraphIdentitySchema } from "#contracts/graph/spec";
|
|
3
|
+
import { PublicPathSchema, Sha256HashSchema } from "#contracts/ids";
|
|
4
|
+
import { APP_LOCALE_CODES, AppLocaleSchema } from "#contracts/locale";
|
|
5
|
+
import { QuranTranslationSchema } from "#contracts/quran/notes";
|
|
6
|
+
import { QuranAttributionRowSchema } from "#contracts/quran/source";
|
|
7
|
+
import { QURAN_CHUNK_SIZE, QuranSurahNumberSchema, QuranSurahRowSchema, QuranTafsirLocaleSchema, } from "#contracts/quran/spec";
|
|
8
|
+
import { QuranMeaningfulTextSchema, QuranTextSchema, } from "#contracts/quran/text";
|
|
9
|
+
/** One locale-indexed QuranEnc translation. */
|
|
10
|
+
export const QuranLocalizedTranslationSchema = Schema.Struct({
|
|
11
|
+
appLocale: AppLocaleSchema,
|
|
12
|
+
value: QuranTranslationSchema,
|
|
13
|
+
});
|
|
14
|
+
/** Checks translation entries for unique canonical app-locale order. */
|
|
15
|
+
function hasCanonicalTranslations(translations) {
|
|
16
|
+
return translations.every((translation, index) => {
|
|
17
|
+
const previous = translations[index - 1];
|
|
18
|
+
return (previous === undefined ||
|
|
19
|
+
APP_LOCALE_CODES.indexOf(previous.appLocale) <
|
|
20
|
+
APP_LOCALE_CODES.indexOf(translation.appLocale));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const QuranTranslationListSchema = Schema.NonEmptyArray(QuranLocalizedTranslationSchema).pipe(Schema.check(Schema.makeFilter(hasCanonicalTranslations, {
|
|
24
|
+
message: "Quran translations must use unique canonical app-locale order.",
|
|
25
|
+
})));
|
|
26
|
+
/** Optional Tafsir entry available only for reviewed locales. */
|
|
27
|
+
const QuranRuntimeTafsirSchema = Schema.Struct({
|
|
28
|
+
appLocale: QuranTafsirLocaleSchema,
|
|
29
|
+
footnotes: Schema.NullOr(Schema.String),
|
|
30
|
+
text: QuranMeaningfulTextSchema,
|
|
31
|
+
});
|
|
32
|
+
/** One exact verse with explicit translation locale entries. */
|
|
33
|
+
export const QuranRuntimeVerseSchema = Schema.Struct({
|
|
34
|
+
meta: Schema.Struct({
|
|
35
|
+
hizbQuarter: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
36
|
+
juz: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
37
|
+
manzil: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
38
|
+
page: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
39
|
+
ruku: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
40
|
+
sajda: Schema.NullOr(Schema.Literals(["obligatory", "recommended"])),
|
|
41
|
+
}),
|
|
42
|
+
number: Schema.Struct({
|
|
43
|
+
inQuran: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
44
|
+
inSurah: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
45
|
+
}),
|
|
46
|
+
tafsir: Schema.Array(QuranRuntimeTafsirSchema).pipe(Schema.check(Schema.isMaxLength(1))),
|
|
47
|
+
text: QuranTextSchema,
|
|
48
|
+
translations: QuranTranslationListSchema,
|
|
49
|
+
});
|
|
50
|
+
/** Checks one chunk's declared bounds against every ordered verse. */
|
|
51
|
+
function hasCoherentChunk(input) {
|
|
52
|
+
if (input.lastVerse - input.firstVerse + 1 !== input.verses.length) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return input.verses.every((verse, index) => verse.number.inSurah === input.firstVerse + index &&
|
|
56
|
+
verse.number.inQuran === input.firstQuranNumber + index);
|
|
57
|
+
}
|
|
58
|
+
/** Immutable bounded runtime row containing ordered verses. */
|
|
59
|
+
export const QuranChunkRowSchema = Schema.Struct({
|
|
60
|
+
firstQuranNumber: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
61
|
+
firstVerse: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
62
|
+
kind: Schema.Literal("quran-chunk"),
|
|
63
|
+
lastVerse: Schema.Int.pipe(Schema.check(Schema.isGreaterThan(0))),
|
|
64
|
+
surahNumber: QuranSurahNumberSchema,
|
|
65
|
+
verses: Schema.NonEmptyArray(QuranRuntimeVerseSchema).pipe(Schema.check(Schema.isMaxLength(QURAN_CHUNK_SIZE))),
|
|
66
|
+
}).pipe(Schema.check(Schema.makeFilter(hasCoherentChunk, {
|
|
67
|
+
message: "Expected one contiguous Quran runtime chunk.",
|
|
68
|
+
})));
|
|
69
|
+
/** One locale-specific Quran route and full-text search document. */
|
|
70
|
+
export const QuranSearchRowSchema = Schema.Struct({
|
|
71
|
+
appLocale: AppLocaleSchema,
|
|
72
|
+
graph: LearningGraphIdentitySchema,
|
|
73
|
+
kind: Schema.Literal("quran-search"),
|
|
74
|
+
route: PublicPathSchema,
|
|
75
|
+
surahNumber: QuranSurahNumberSchema,
|
|
76
|
+
text: QuranMeaningfulTextSchema,
|
|
77
|
+
title: QuranMeaningfulTextSchema,
|
|
78
|
+
});
|
|
79
|
+
/** Complete structured Quran row vocabulary. */
|
|
80
|
+
export const QuranRowPayloadSchema = Schema.Union([
|
|
81
|
+
QuranAttributionRowSchema,
|
|
82
|
+
QuranSurahRowSchema,
|
|
83
|
+
QuranChunkRowSchema,
|
|
84
|
+
QuranSearchRowSchema,
|
|
85
|
+
]);
|
|
86
|
+
/** One content-addressed row bound to an immutable Quran snapshot. */
|
|
87
|
+
export const QuranSnapshotRowSchema = Schema.Struct({
|
|
88
|
+
payload: QuranRowPayloadSchema,
|
|
89
|
+
rowHash: Sha256HashSchema,
|
|
90
|
+
snapshotId: Sha256HashSchema,
|
|
91
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Semantic wire identity of the current localized Quran snapshot. */
|
|
3
|
+
export declare const QURAN_SNAPSHOT_FORMAT = "localized-quran-snapshot";
|
|
4
|
+
/** Production publication status derived from reviewed provenance records. */
|
|
5
|
+
export declare const QuranProvenanceStatusSchema: Schema.Literals<readonly ["approved", "blocked"]>;
|
|
6
|
+
export type QuranProvenanceStatus = typeof QuranProvenanceStatusSchema.Type;
|
|
7
|
+
/** Immutable current Quran facts before content-addressed identity. */
|
|
8
|
+
export declare const QuranSnapshotFactsSchema: Schema.Struct<{
|
|
9
|
+
activeAppLocales: Schema.NonEmptyArray<Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">>;
|
|
10
|
+
attributionCount: Schema.Int;
|
|
11
|
+
chunkCount: Schema.Int;
|
|
12
|
+
projectionCount: Schema.Int;
|
|
13
|
+
projectionDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
14
|
+
provenanceDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
15
|
+
provenanceStatus: Schema.Literals<readonly ["approved", "blocked"]>;
|
|
16
|
+
runtimeCount: Schema.Int;
|
|
17
|
+
runtimeDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
18
|
+
searchCount: Schema.Int;
|
|
19
|
+
searchDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
20
|
+
sourceBytes: Schema.Int;
|
|
21
|
+
sourceDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
22
|
+
sourceFileCount: Schema.Int;
|
|
23
|
+
surahCount: Schema.Int;
|
|
24
|
+
tafsirLocales: Schema.$Array<Schema.Literal<"id">>;
|
|
25
|
+
verseCount: Schema.Int;
|
|
26
|
+
}>;
|
|
27
|
+
export type QuranSnapshotFacts = typeof QuranSnapshotFactsSchema.Type;
|
|
28
|
+
/** Immutable identity and completeness proof for one Quran snapshot. */
|
|
29
|
+
export declare const QuranSnapshotSchema: Schema.Struct<{
|
|
30
|
+
readonly activeAppLocales: Schema.NonEmptyArray<Schema.brand<Schema.Literals<readonly ["en", "id", "de"]>, "@NakafaAI/AksaraAppLocale">>;
|
|
31
|
+
readonly attributionCount: Schema.Int;
|
|
32
|
+
readonly chunkCount: Schema.Int;
|
|
33
|
+
readonly projectionCount: Schema.Int;
|
|
34
|
+
readonly projectionDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
35
|
+
readonly provenanceDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
36
|
+
readonly provenanceStatus: Schema.Literals<readonly ["approved", "blocked"]>;
|
|
37
|
+
readonly runtimeCount: Schema.Int;
|
|
38
|
+
readonly runtimeDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
39
|
+
readonly searchCount: Schema.Int;
|
|
40
|
+
readonly searchDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
41
|
+
readonly sourceBytes: Schema.Int;
|
|
42
|
+
readonly sourceDigest: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
43
|
+
readonly sourceFileCount: Schema.Int;
|
|
44
|
+
readonly surahCount: Schema.Int;
|
|
45
|
+
readonly tafsirLocales: Schema.$Array<Schema.Literal<"id">>;
|
|
46
|
+
readonly verseCount: Schema.Int;
|
|
47
|
+
readonly format: Schema.Literal<"localized-quran-snapshot">;
|
|
48
|
+
readonly snapshotId: Schema.brand<Schema.String, "@NakafaAI/AksaraSha256Hash">;
|
|
49
|
+
}>;
|
|
50
|
+
export type QuranSnapshot = typeof QuranSnapshotSchema.Type;
|