is-mahram
Version:
A TypeScript library to determine if a person is a mahram based on Islamic jurisprudence.
299 lines (290 loc) • 8.04 kB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __moduleCache = /* @__PURE__ */ new WeakMap;
var __toCommonJS = (from) => {
var entry = __moduleCache.get(from), desc;
if (entry)
return entry;
entry = __defProp({}, "__esModule", { value: true });
if (from && typeof from === "object" || typeof from === "function")
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
}));
__moduleCache.set(from, entry);
return entry;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: (newValue) => all[name] = () => newValue
});
};
// src/index.ts
var exports_src = {};
__export(exports_src, {
isMahram: () => isMahram,
SucklingMotherMustBeFemaleError: () => SucklingMotherMustBeFemaleError,
SpouseMustBeOppositeGenderError: () => SpouseMustBeOppositeGenderError,
Person: () => Person,
MotherMustBeFemaleError: () => MotherMustBeFemaleError,
FatherMustBeMaleError: () => FatherMustBeMaleError
});
module.exports = __toCommonJS(exports_src);
// src/is-mahram.ts
function isMahram(personA, personB) {
if (personA.getId() === personB.getId()) {
return true;
}
if (personA.getSpouses().has(personB)) {
return true;
}
if (isBloodMahram(personA, personB)) {
return true;
}
if (isMarriageMahram(personA, personB)) {
return true;
}
if (isSucklingMahram(personA, personB)) {
return true;
}
return false;
}
function isBloodMahram(personA, personB) {
if (isAncestor(personA, personB) || isAncestor(personB, personA)) {
return true;
}
if (isSibling(personA, personB)) {
return true;
}
if (isAuntOrUncle(personA, personB) || isAuntOrUncle(personB, personA)) {
return true;
}
return false;
}
function isMarriageMahram(personA, personB) {
for (const spouse of personA.getSpouses()) {
if (isAncestor(personB, spouse)) {
return true;
}
}
for (const spouse of personB.getSpouses()) {
if (isAncestor(personA, spouse)) {
return true;
}
}
for (const spouse of personA.getSpouses()) {
if (isDescendant(personB, spouse)) {
return true;
}
}
for (const spouse of personB.getSpouses()) {
if (isDescendant(personA, spouse)) {
return true;
}
}
const { father: fatherA, mother: motherA } = personA.getParents();
const { father: fatherB, mother: motherB } = personB.getParents();
if (fatherA?.getSpouses().has(personB)) {
return true;
}
if (motherA?.getSpouses().has(personB)) {
return true;
}
if (fatherB?.getSpouses().has(personA)) {
return true;
}
if (motherB?.getSpouses().has(personA)) {
return true;
}
const childrenOfA = getChildren(personA);
for (const child of childrenOfA) {
if (child?.getSpouses().has(personB)) {
return true;
}
}
const childrenOfB = getChildren(personB);
for (const child of childrenOfB) {
if (child?.getSpouses().has(personA)) {
return true;
}
}
return false;
}
function isSucklingMahram(personA, personB) {
const sucklingParentsA = getSucklingParents(personA);
const sucklingParentsB = getSucklingParents(personB);
if (!sucklingParentsA && !sucklingParentsB)
return false;
if (sucklingParentsB && sucklingParentsB.mother === personA || sucklingParentsB && sucklingParentsB.father === personA) {
return true;
}
if (sucklingParentsA && sucklingParentsA.mother === personB || sucklingParentsA && sucklingParentsA.father === personB) {
return true;
}
if (sucklingParentsA && sucklingParentsB && sucklingParentsA.mother === sucklingParentsB.mother) {
return true;
}
const sucklingMotherA = personA.getSucklingMother();
const sucklingMotherB = personB.getSucklingMother();
if (sucklingMotherA && isBloodMahram(sucklingMotherA, personB)) {
return true;
}
if (sucklingMotherB && isBloodMahram(sucklingMotherB, personA)) {
return true;
}
return false;
}
function isAncestor(potentialAncestor, person) {
const { father, mother } = person.getParents();
if (!father && !mother) {
return false;
}
if (father === potentialAncestor || mother === potentialAncestor) {
return true;
}
return !!(father && isAncestor(potentialAncestor, father) || mother && isAncestor(potentialAncestor, mother));
}
function isDescendant(potentialDescendant, person) {
return isAncestor(person, potentialDescendant);
}
function isSibling(personA, personB) {
const { father: fatherA, mother: motherA } = personA.getParents();
const { father: fatherB, mother: motherB } = personB.getParents();
if (fatherA && motherA && fatherB && motherB) {
return fatherA === fatherB || motherA === motherB;
}
return false;
}
function isAuntOrUncle(potentialAuntOrUncle, person) {
const { father, mother } = person.getParents();
if (father && isSibling(potentialAuntOrUncle, father)) {
return true;
}
if (mother && isSibling(potentialAuntOrUncle, mother)) {
return true;
}
return false;
}
function getChildren(person) {
return [];
}
function getSucklingParents(person) {
const sucklingMother = person.getSucklingMother();
if (!sucklingMother) {
return null;
}
return {
mother: sucklingMother,
father: Array.from(sucklingMother.getSpouses())[0] || null
};
}
// src/errors.ts
class FatherMustBeMaleError extends Error {
constructor() {
super("Father must be male");
this.name = "FatherMustBeMaleError";
}
}
class MotherMustBeFemaleError extends Error {
constructor() {
super("Mother must be female");
this.name = "MotherMustBeFemaleError";
}
}
class SucklingMotherMustBeFemaleError extends Error {
constructor() {
super("Suckling mother must be femalre");
this.name = "SucklingMotherMustBeFemaleError";
}
}
class SpouseMustBeOppositeGenderError extends Error {
constructor() {
super("Spouse must be of opposite gender");
this.name = "SpouseMustBeOppositeGenderError";
}
}
// src/util.ts
var generateId = () => {
return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
};
// src/person.ts
class Person {
name;
gender;
id;
parents = {
father: null,
mother: null
};
spouses = new Set;
sucklingMother = null;
constructor(name, gender) {
this.name = name;
this.gender = gender;
this.id = generateId();
}
setName(name) {
this.name = name;
}
setFather(father) {
if (father.gender !== "Male")
throw new FatherMustBeMaleError;
this.parents.father = father;
if (this.parents.mother && !this.parents.mother.getSpouses().has(father)) {
this.parents.mother.addSpouse(father);
}
}
setMother(mother) {
if (mother.gender !== "Female")
throw new MotherMustBeFemaleError;
this.parents.mother = mother;
if (this.parents.father && !this.parents.father.getSpouses().has(mother)) {
this.parents.father.addSpouse(mother);
}
}
addSpouse(spouse) {
if (this.gender === spouse.gender) {
throw new SpouseMustBeOppositeGenderError;
}
if (!this.spouses.has(spouse)) {
this.spouses.add(spouse);
spouse.spouses.add(this);
}
}
setSucklingMother(wetNurse) {
if (wetNurse.gender !== "Female") {
throw new SucklingMotherMustBeFemaleError;
}
this.sucklingMother = wetNurse;
}
getId() {
return this.id;
}
getName() {
return this.name;
}
getGender() {
return this.gender;
}
getParents() {
return this.parents;
}
getFather() {
return this.parents.father;
}
getMother() {
return this.parents.mother;
}
getSpouses() {
return this.spouses;
}
getSucklingMother() {
return this.sucklingMother;
}
}