fix(documentation): patch publicodes 1.2 pour récupérer le fix du scroll de la documentation
parent
4907585803
commit
4c7a01150c
|
@ -7,6 +7,7 @@ package-lock.json
|
|||
node_modules/
|
||||
.env
|
||||
dist/
|
||||
!publicodes/dist/
|
||||
storybook-static/
|
||||
|
||||
# Local Netlify folder
|
||||
|
@ -23,4 +24,4 @@ storybook-static/
|
|||
!**/.yarn/plugins
|
||||
!**/.yarn/releases
|
||||
!**/.yarn/sdks
|
||||
!**/.yarn/versions
|
||||
!**/.yarn/versions
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-vitest": "^0.3.22",
|
||||
"prettier": "^3.0.3",
|
||||
"publicodes": "^1.2.0",
|
||||
"publicodes": "file:./publicodes",
|
||||
"rimraf": "^5.0.1"
|
||||
},
|
||||
"resolutions": {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
# `publicodes`
|
||||
|
||||
The publicodes engine that interprets a set of publicodes rules.
|
||||
|
||||
[Documentation](https://publi.codes/docs/api/core)
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
npm install publicodes
|
||||
```
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,639 @@
|
|||
type ArrondiNode = {
|
||||
explanation: {
|
||||
arrondi: ASTNode;
|
||||
valeur: ASTNode;
|
||||
};
|
||||
nodeKind: 'arrondi';
|
||||
};
|
||||
|
||||
type TrancheNode = {
|
||||
taux: ASTNode;
|
||||
} | {
|
||||
montant: ASTNode;
|
||||
};
|
||||
type TrancheNodes = Array<TrancheNode & {
|
||||
plafond?: ASTNode;
|
||||
isActive?: boolean;
|
||||
}>;
|
||||
|
||||
type BarèmeNode = {
|
||||
explanation: {
|
||||
tranches: TrancheNodes;
|
||||
multiplicateur: ASTNode;
|
||||
assiette: ASTNode;
|
||||
};
|
||||
nodeKind: 'barème';
|
||||
};
|
||||
|
||||
type ConditionNode = {
|
||||
explanation: {
|
||||
si: ASTNode;
|
||||
alors: ASTNode;
|
||||
sinon: ASTNode;
|
||||
};
|
||||
nodeKind: 'condition';
|
||||
};
|
||||
|
||||
type NodesTypes = WeakMap<ASTNode, InferedType>;
|
||||
type InferedType = {
|
||||
isNullable: boolean | undefined;
|
||||
} & Pick<ConstantNode, 'type'>;
|
||||
|
||||
type Rule = {
|
||||
formule?: Record<string, unknown> | string;
|
||||
valeur?: Record<string, unknown> | string;
|
||||
question?: string;
|
||||
description?: string;
|
||||
unité?: string;
|
||||
acronyme?: string;
|
||||
exemples?: any;
|
||||
résumé?: string;
|
||||
icônes?: string;
|
||||
titre?: string;
|
||||
sévérité?: string;
|
||||
type?: string;
|
||||
experimental?: 'oui';
|
||||
'possiblement non applicable'?: 'oui';
|
||||
privé?: 'oui';
|
||||
note?: string;
|
||||
remplace?: Remplace | Array<Remplace>;
|
||||
'rend non applicable'?: Remplace | Array<Remplace>;
|
||||
suggestions?: Record<string, string | number | Record<string, unknown>>;
|
||||
références?: {
|
||||
[source: string]: string;
|
||||
};
|
||||
API?: string;
|
||||
'identifiant court'?: string;
|
||||
} & Record<string, unknown>;
|
||||
type Remplace = {
|
||||
'références à': string;
|
||||
dans?: Array<string> | string;
|
||||
'sauf dans'?: Array<string> | string;
|
||||
priorité?: number;
|
||||
} | string;
|
||||
type RuleNode<Name extends string = string> = {
|
||||
dottedName: Name;
|
||||
title: string;
|
||||
nodeKind: 'rule';
|
||||
virtualRule: boolean;
|
||||
private: boolean;
|
||||
rawNode: Rule;
|
||||
replacements: Array<ReplacementRule>;
|
||||
explanation: {
|
||||
valeur: ASTNode;
|
||||
parents: Array<ASTNode>;
|
||||
nullableParent?: ASTNode;
|
||||
ruleDisabledByItsParent: boolean;
|
||||
};
|
||||
suggestions: Record<string, ASTNode>;
|
||||
'identifiant court'?: string;
|
||||
};
|
||||
|
||||
type ReplacementRule = {
|
||||
nodeKind: 'replacementRule';
|
||||
definitionRule: ASTNode<'reference'> & {
|
||||
dottedName: string;
|
||||
};
|
||||
replacedReference: ASTNode<'reference'>;
|
||||
priority?: number;
|
||||
whiteListedNames: Array<ASTNode<'reference'>>;
|
||||
rawNode: any;
|
||||
blackListedNames: Array<ASTNode<'reference'>>;
|
||||
remplacementRuleId: number;
|
||||
replaceByNonApplicable: boolean;
|
||||
};
|
||||
|
||||
type getUnitKey = (writtenUnit: string) => string;
|
||||
type formatUnit = (unit: string, count: number) => string;
|
||||
declare const parseUnit: (string: string, getUnitKey?: getUnitKey) => Unit;
|
||||
declare function serializeUnit(rawUnit: Unit | undefined | string, count?: number, formatUnit?: formatUnit): string | undefined;
|
||||
|
||||
type Context<RuleNames extends string = string> = {
|
||||
dottedName: RuleNames | '';
|
||||
parsedRules: ParsedRules<RuleNames>;
|
||||
nodesTypes: NodesTypes;
|
||||
referencesMaps: ReferencesMaps<RuleNames>;
|
||||
rulesReplacements: RulesReplacements<RuleNames>;
|
||||
getUnitKey?: getUnitKey;
|
||||
logger: Logger;
|
||||
inversionMaxIterations?: number;
|
||||
/**
|
||||
* Don't throw an error if the parent of a rule is not found.
|
||||
* This is useful to parse partial rule sets (e.g. optimized ones).
|
||||
*/
|
||||
allowOrphanRules: boolean;
|
||||
/**
|
||||
* This is used to generate unique IDs for sub-engines, we need to generate them at
|
||||
* */
|
||||
subEngineIncrementingNumber?: number;
|
||||
};
|
||||
type RulesReplacements<RuleNames extends string> = Partial<Record<RuleNames, ReplacementRule[]>>;
|
||||
type ReferencesMaps<Names extends string> = {
|
||||
referencesIn: Map<Names, Set<Names>>;
|
||||
rulesThatUse: Map<Names, Set<Names>>;
|
||||
};
|
||||
type RawRule = Omit<Rule, 'nom'> | string | number | null;
|
||||
type RawPublicodes<RuleNames extends string> = Partial<Record<RuleNames, RawRule>>;
|
||||
declare function parsePublicodes<ContextNames extends string, NewRulesNames extends string>(rawRules: RawPublicodes<NewRulesNames>, partialContext?: Partial<Context<ContextNames>>): Pick<Context<ContextNames | NewRulesNames>, 'parsedRules' | 'nodesTypes' | 'referencesMaps' | 'rulesReplacements'>;
|
||||
|
||||
type ReferenceNode = {
|
||||
nodeKind: 'reference';
|
||||
name: string;
|
||||
contextDottedName: string;
|
||||
dottedName?: string;
|
||||
title?: string;
|
||||
acronym?: string;
|
||||
};
|
||||
|
||||
type ContextNode = {
|
||||
explanation: {
|
||||
valeur: ASTNode;
|
||||
contexte: Array<[ReferenceNode, ASTNode]>;
|
||||
subEngineId: number;
|
||||
};
|
||||
nodeKind: 'contexte';
|
||||
};
|
||||
|
||||
type DuréeNode = {
|
||||
explanation: {
|
||||
depuis: ASTNode;
|
||||
"jusqu'à": ASTNode;
|
||||
};
|
||||
unit: Unit;
|
||||
nodeKind: 'durée';
|
||||
};
|
||||
|
||||
type EstNonDéfiniNode = {
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'est non défini';
|
||||
};
|
||||
|
||||
type EstNonApplicableNode = {
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'est non applicable';
|
||||
};
|
||||
|
||||
type GrilleNode = {
|
||||
explanation: {
|
||||
assiette: ASTNode;
|
||||
multiplicateur: ASTNode;
|
||||
tranches: TrancheNodes;
|
||||
};
|
||||
nodeKind: 'grille';
|
||||
};
|
||||
|
||||
type InversionNode = {
|
||||
explanation: {
|
||||
ruleToInverse: string;
|
||||
inversionCandidates: Array<ReferenceNode>;
|
||||
unit?: Unit;
|
||||
inversionGoal?: ASTNode;
|
||||
numberOfIteration?: number;
|
||||
inversionFail?: boolean;
|
||||
};
|
||||
nodeKind: 'inversion';
|
||||
};
|
||||
|
||||
type PossibilityNode = {
|
||||
explanation: Array<ASTNode>;
|
||||
'choix obligatoire'?: 'oui' | 'non';
|
||||
context: string;
|
||||
nodeKind: 'une possibilité';
|
||||
};
|
||||
|
||||
declare const knownOperations: {
|
||||
readonly '*': readonly [(a: any, b: any) => number, "×"];
|
||||
readonly '/': readonly [(a: any, b: any) => number, "∕"];
|
||||
readonly '+': readonly [(a: any, b: any) => any];
|
||||
readonly '-': readonly [(a: any, b: any) => number, "−"];
|
||||
readonly '<': readonly [(a: any, b: any) => boolean];
|
||||
readonly '<=': readonly [(a: any, b: any) => boolean, "≤"];
|
||||
readonly '>': readonly [(a: any, b: any) => boolean];
|
||||
readonly '>=': readonly [(a: any, b: any) => boolean, "≥"];
|
||||
readonly '=': readonly [(a: any, b: any) => boolean];
|
||||
readonly '!=': readonly [(a: any, b: any) => boolean, "≠"];
|
||||
readonly et: readonly [(a: any, b: any) => any];
|
||||
readonly ou: readonly [(a: any, b: any) => any];
|
||||
};
|
||||
type OperationNode = {
|
||||
nodeKind: 'operation';
|
||||
explanation: [ASTNode, ASTNode];
|
||||
operationKind: keyof typeof knownOperations;
|
||||
operator: string;
|
||||
};
|
||||
|
||||
type RésoudreRéférenceCirculaireNode = {
|
||||
explanation: {
|
||||
ruleToSolve: string;
|
||||
valeur: ASTNode;
|
||||
};
|
||||
nodeKind: 'résoudre référence circulaire';
|
||||
};
|
||||
|
||||
type SimplifierUnitéNode = {
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'simplifier unité';
|
||||
};
|
||||
|
||||
type TauxProgressifNode = {
|
||||
explanation: {
|
||||
tranches: TrancheNodes;
|
||||
multiplicateur: ASTNode;
|
||||
assiette: ASTNode;
|
||||
};
|
||||
nodeKind: 'taux progressif';
|
||||
};
|
||||
|
||||
declare const NAME: "texte";
|
||||
type TexteNode = {
|
||||
explanation: Array<ASTNode | string>;
|
||||
nodeKind: typeof NAME;
|
||||
};
|
||||
|
||||
type UnitéNode = {
|
||||
unit: Unit;
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'unité';
|
||||
};
|
||||
|
||||
type VariableManquanteNode = {
|
||||
missingVariable: string;
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'variable manquante';
|
||||
};
|
||||
|
||||
type VariationNode = {
|
||||
explanation: Array<{
|
||||
condition: ASTNode;
|
||||
consequence: ASTNode;
|
||||
satisfied?: boolean;
|
||||
}>;
|
||||
nodeKind: 'variations';
|
||||
};
|
||||
|
||||
type ConstantNode = {
|
||||
type: 'boolean' | 'number' | 'string' | 'date' | undefined;
|
||||
nodeValue: Evaluation;
|
||||
nodeKind: 'constant';
|
||||
isNullable?: boolean;
|
||||
isDefault?: boolean;
|
||||
fullPrecision?: boolean;
|
||||
};
|
||||
type PossibleNodes = RuleNode | ReferenceNode | ArrondiNode | BarèmeNode | DuréeNode | GrilleNode | EstNonApplicableNode | EstNonDéfiniNode | InversionNode | OperationNode | PossibilityNode | ContextNode | SimplifierUnitéNode | RésoudreRéférenceCirculaireNode | TauxProgressifNode | UnitéNode | VariationNode | ConditionNode | ConstantNode | ReplacementRule | VariableManquanteNode | TexteNode;
|
||||
type NodeKind = PossibleNodes['nodeKind'];
|
||||
type ASTNode<N extends NodeKind = NodeKind> = PossibleNodes & {
|
||||
nodeKind: N;
|
||||
isDefault?: boolean;
|
||||
sourceMap?: {
|
||||
mecanismName: string;
|
||||
args: Record<string, ASTNode | Array<ASTNode>>;
|
||||
};
|
||||
rawNode?: string | Record<string, unknown>;
|
||||
} & (EvaluationDecoration<Types> | {});
|
||||
type ASTTransformer = (n: ASTNode) => ASTNode;
|
||||
type TraverseFunction<K extends NodeKind> = (fn: ASTTransformer, node: ASTNode<K>) => ASTNode<K>;
|
||||
type BaseUnit = string;
|
||||
type Unit = {
|
||||
numerators: Array<BaseUnit>;
|
||||
denominators: Array<BaseUnit>;
|
||||
};
|
||||
type EvaluationDecoration<T extends Types> = {
|
||||
nodeValue: Evaluation<T>;
|
||||
unit?: Unit;
|
||||
traversedVariables?: Array<string>;
|
||||
missingVariables: MissingVariables;
|
||||
};
|
||||
type Types = number | boolean | string | Record<string, unknown>;
|
||||
type Evaluation<T extends Types = Types> = T | null | undefined;
|
||||
type EvaluatedNode<K extends NodeKind = NodeKind, T extends Types = Types> = EvaluationDecoration<T> & ASTNode<K>;
|
||||
type MissingVariables = Record<string, number>;
|
||||
|
||||
type GraphCycles = string[][];
|
||||
type RawRules = Parameters<typeof parsePublicodes>[0];
|
||||
/**
|
||||
* This function is useful so as to print the dependencies at each node of the
|
||||
* cycle.
|
||||
* ⚠️ Indeed, the findCycles function returns the cycle found using the
|
||||
* Tarjan method, which is **not necessarily the smallest cycle**. However, the
|
||||
* smallest cycle is more readable.
|
||||
*/
|
||||
declare function cyclicDependencies(rawRules: RawRules): [GraphCycles, string[]];
|
||||
|
||||
/**
|
||||
* Returns the last part of a dottedName (the leaf).
|
||||
*/
|
||||
declare const nameLeaf: (dottedName: string) => string;
|
||||
/**
|
||||
* Encodes a dottedName for the URL to be secure.
|
||||
* @see {@link decodeRuleName}
|
||||
*/
|
||||
declare const encodeRuleName: (dottedName: string) => string;
|
||||
/**
|
||||
* Decodes an encoded dottedName.
|
||||
* @see {@link encodeRuleName}
|
||||
*/
|
||||
declare const decodeRuleName: (dottedName: string) => string;
|
||||
/**
|
||||
* Return dottedName from contextName
|
||||
*/
|
||||
declare const contextNameToDottedName: (contextName: string) => string;
|
||||
/**
|
||||
* Returns the parent dottedName
|
||||
*/
|
||||
declare const ruleParent: (dottedName: string) => string;
|
||||
/**
|
||||
* Returns an array of dottedName from near parent to far parent.
|
||||
*/
|
||||
declare function ruleParents(dottedName: string): Array<string>;
|
||||
/**
|
||||
* Returns an array of all child rules of a dottedName
|
||||
*/
|
||||
declare const getChildrenRules: (parsedRules: ParsedRules<string>, dottedName: string) => string[];
|
||||
/**
|
||||
* Finds the common ancestor of two dottedName
|
||||
*/
|
||||
declare function findCommonAncestor(dottedName1: string, dottedName2: string): string;
|
||||
/**
|
||||
* Check wether a rule is accessible from a namespace.
|
||||
*
|
||||
* Takes into account that some namespace can be `private`, i.e. that they can only be
|
||||
* accessed by immediate parent, children or siblings.
|
||||
*
|
||||
* @param rules The parsed rules
|
||||
* @param contextName The context of the call
|
||||
* @param name The namespace checked for accessibility
|
||||
*/
|
||||
declare function isAccessible(rules: Record<string, RuleNode>, contextName: string, name: string): boolean;
|
||||
/**
|
||||
* Check wether a rule is tagged as experimental.
|
||||
*
|
||||
* Takes into account the a children of an experimental rule is also experimental
|
||||
*
|
||||
* @param rules The parsed rules
|
||||
* @param name The namespace checked for experimental
|
||||
*/
|
||||
declare function isExperimental(rules: Record<string, RuleNode>, name: string): boolean;
|
||||
declare function disambiguateReference<R extends Record<string, RuleNode>>(rules: R, referencedFrom: string | undefined, partialName: string): keyof R;
|
||||
declare function ruleWithDedicatedDocumentationPage(rule: any): boolean;
|
||||
declare function updateReferencesMapsFromReferenceNode(node: ASTNode, referencesMaps: ReferencesMaps<string>, ruleDottedName?: string): void;
|
||||
declare function disambiguateReferenceNode(node: ASTNode, parsedRules: ParsedRules<string>): ReferenceNode | undefined;
|
||||
|
||||
declare const ruleUtils_contextNameToDottedName: typeof contextNameToDottedName;
|
||||
declare const ruleUtils_cyclicDependencies: typeof cyclicDependencies;
|
||||
declare const ruleUtils_decodeRuleName: typeof decodeRuleName;
|
||||
declare const ruleUtils_disambiguateReference: typeof disambiguateReference;
|
||||
declare const ruleUtils_disambiguateReferenceNode: typeof disambiguateReferenceNode;
|
||||
declare const ruleUtils_encodeRuleName: typeof encodeRuleName;
|
||||
declare const ruleUtils_findCommonAncestor: typeof findCommonAncestor;
|
||||
declare const ruleUtils_getChildrenRules: typeof getChildrenRules;
|
||||
declare const ruleUtils_isAccessible: typeof isAccessible;
|
||||
declare const ruleUtils_isExperimental: typeof isExperimental;
|
||||
declare const ruleUtils_nameLeaf: typeof nameLeaf;
|
||||
declare const ruleUtils_ruleParent: typeof ruleParent;
|
||||
declare const ruleUtils_ruleParents: typeof ruleParents;
|
||||
declare const ruleUtils_ruleWithDedicatedDocumentationPage: typeof ruleWithDedicatedDocumentationPage;
|
||||
declare const ruleUtils_updateReferencesMapsFromReferenceNode: typeof updateReferencesMapsFromReferenceNode;
|
||||
declare namespace ruleUtils {
|
||||
export {
|
||||
ruleUtils_contextNameToDottedName as contextNameToDottedName,
|
||||
ruleUtils_cyclicDependencies as cyclicDependencies,
|
||||
ruleUtils_decodeRuleName as decodeRuleName,
|
||||
ruleUtils_disambiguateReference as disambiguateReference,
|
||||
ruleUtils_disambiguateReferenceNode as disambiguateReferenceNode,
|
||||
ruleUtils_encodeRuleName as encodeRuleName,
|
||||
ruleUtils_findCommonAncestor as findCommonAncestor,
|
||||
ruleUtils_getChildrenRules as getChildrenRules,
|
||||
ruleUtils_isAccessible as isAccessible,
|
||||
ruleUtils_isExperimental as isExperimental,
|
||||
ruleUtils_nameLeaf as nameLeaf,
|
||||
ruleUtils_ruleParent as ruleParent,
|
||||
ruleUtils_ruleParents as ruleParents,
|
||||
ruleUtils_ruleWithDedicatedDocumentationPage as ruleWithDedicatedDocumentationPage,
|
||||
ruleUtils_updateReferencesMapsFromReferenceNode as updateReferencesMapsFromReferenceNode,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
This function creates a transormation of the AST from on a simpler
|
||||
callback function `fn`
|
||||
|
||||
`fn` will be called with the nodes of the ASTTree during the exploration
|
||||
|
||||
The outcome of the callback function has an influence on the exploration of the AST :
|
||||
- `false`, the node is not updated and the exploration does not continue further down this branch
|
||||
- `undefined`, the node is not updated but the exploration continues and its children will be transformed
|
||||
- `ASTNode`, the node is transformed to the new value and the exploration does not continue further down the branch
|
||||
|
||||
`updateFn` : It is possible to specifically use the updated version of a child
|
||||
by using the function passed as second argument. The returned value will be the
|
||||
transformed version of the node.
|
||||
*/
|
||||
declare function makeASTTransformer(fn: (node: ASTNode, transform: ASTTransformer) => ASTNode | undefined | false, stopOnUpdate?: boolean): ASTTransformer;
|
||||
/**
|
||||
* This function allows to construct a specific value while exploring the AST with
|
||||
* a simple reducing function as argument.
|
||||
*
|
||||
* `fn` will be called with the currently reduced value `acc` and the current node of the AST
|
||||
*
|
||||
* If the callback function returns:
|
||||
* - `undefined`, the exploration continues further down and all the children are reduced
|
||||
* successively to a single value
|
||||
* - `T`, the reduced value is returned
|
||||
*
|
||||
* `reduceFn` : It is possible to specifically use the reduced value of a child
|
||||
* by using the function passed as second argument. The returned value will be the reduced version
|
||||
* of the node
|
||||
*/
|
||||
declare function reduceAST<T>(fn: (acc: T, n: ASTNode, reduceFn: (n: ASTNode) => T) => T | undefined, start: T, node: ASTNode): T;
|
||||
/**
|
||||
* Apply a transform function on children. Not recursive.
|
||||
*/
|
||||
declare const traverseASTNode: TraverseFunction<NodeKind>;
|
||||
|
||||
/**
|
||||
* Each error name with corresponding type in info value
|
||||
*/
|
||||
interface PublicodesErrorTypes {
|
||||
InternalError: {
|
||||
dottedName?: string;
|
||||
};
|
||||
EngineError: Record<string, never>;
|
||||
SyntaxError: {
|
||||
dottedName: string;
|
||||
};
|
||||
EvaluationError: {
|
||||
dottedName: string;
|
||||
};
|
||||
UnknownRule: {
|
||||
dottedName: string;
|
||||
};
|
||||
PrivateRule: {
|
||||
dottedName: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Return true if `error` is a PublicodesError,
|
||||
* use `name` parameter to check and narow error type
|
||||
* @example
|
||||
* try {
|
||||
* new Engine().evaluate()
|
||||
* } catch (error) {
|
||||
* if (isPublicodesError(error, 'EngineError')) {
|
||||
* console.log(error.info)
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
declare const isPublicodesError: <Name extends keyof PublicodesErrorTypes>(error: unknown, name?: Name | undefined) => error is PublicodesError<Name | undefined extends undefined ? keyof PublicodesErrorTypes : Name>;
|
||||
/**
|
||||
* Generic error for Publicodes
|
||||
*/
|
||||
declare class PublicodesError<Name extends keyof PublicodesErrorTypes> extends Error {
|
||||
name: Name;
|
||||
info: PublicodesErrorTypes[Name];
|
||||
constructor(name: Name, message: string, info: PublicodesErrorTypes[Name], originalError?: Error);
|
||||
}
|
||||
|
||||
declare function capitalise0(name: undefined): undefined;
|
||||
declare function capitalise0(name: string): string;
|
||||
type Options$1 = {
|
||||
language?: string;
|
||||
displayedUnit?: string;
|
||||
precision?: number;
|
||||
formatUnit?: formatUnit;
|
||||
};
|
||||
declare function formatValue(value: number | {
|
||||
nodeValue: Evaluation;
|
||||
unit?: Unit;
|
||||
} | undefined, { language, displayedUnit, formatUnit, precision }?: Options$1): any;
|
||||
|
||||
declare function simplifyNodeUnit(node: any): any;
|
||||
|
||||
type BinaryOp = {
|
||||
'+': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'-': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'*': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'/': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'>': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'<': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'>=': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'<=': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'=': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'!=': [ExprAST, ExprAST];
|
||||
};
|
||||
type UnaryOp = {
|
||||
'-': [{
|
||||
value: 0;
|
||||
}, ExprAST];
|
||||
};
|
||||
/** AST of a publicodes expression. */
|
||||
type ExprAST = BinaryOp | UnaryOp | {
|
||||
variable: string;
|
||||
} | {
|
||||
constant: {
|
||||
type: 'number';
|
||||
nodeValue: number;
|
||||
};
|
||||
unité?: string;
|
||||
} | {
|
||||
constant: {
|
||||
type: 'boolean';
|
||||
nodeValue: boolean;
|
||||
};
|
||||
} | {
|
||||
constant: {
|
||||
type: 'string' | 'date';
|
||||
nodeValue: string;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse a publicodes expression into an JSON object representing the AST.
|
||||
*
|
||||
* The parsing is done with the [nearley](https://nearley.js.org/) parser
|
||||
*
|
||||
* @param rawNode The expression to parse
|
||||
* @param dottedName The dottedName of the rule being parsed
|
||||
*
|
||||
* @returns The parsing result as a JSON object
|
||||
*
|
||||
* @throws A `SyntaxError` if the expression is invalid
|
||||
* @throws A `PublicodesInternalError` if the parser is unable to parse the expression
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* parseExpression('20.3 * nombre', 'foo . bar')
|
||||
* // returns { "*": [ { constant: { type: "number", nodeValue: 20.3 } }, { variable:"nombre" } ] }
|
||||
* ```
|
||||
*/
|
||||
declare function parseExpression(rawNode: string, dottedName: string): ExprAST;
|
||||
|
||||
declare function serializeEvaluation(node: EvaluatedNode): string | undefined;
|
||||
|
||||
type Cache = {
|
||||
inversionFail?: boolean;
|
||||
_meta: {
|
||||
evaluationRuleStack: Array<string>;
|
||||
parentRuleStack: Array<string>;
|
||||
currentContexteSituation?: string;
|
||||
};
|
||||
/**
|
||||
* Every time we encounter a reference to a rule in an expression we add it
|
||||
* to the current Set of traversed variables. Because we evaluate the
|
||||
* expression graph “top to bottom” (ie. we start by the high-level goal and
|
||||
* recursively evaluate its dependencies), we need to handle rule
|
||||
* “boundaries”, so that when we “enter” in the evaluation of a dependency,
|
||||
* we start with a clear empty set of traversed variables. Then, when we go
|
||||
* back to the referencer rule, we need to add all to merge the two sets :
|
||||
* rules already traversed in the current expression and the one from the
|
||||
* reference.
|
||||
*/
|
||||
traversedVariablesStack?: Array<Set<string>>;
|
||||
nodes: Map<PublicodesExpression | ASTNode, EvaluatedNode>;
|
||||
};
|
||||
|
||||
type PublicodesExpression = string | Record<string, unknown> | number;
|
||||
type Logger = {
|
||||
log(message: string): void;
|
||||
warn(message: string): void;
|
||||
error(message: string): void;
|
||||
};
|
||||
type Options = Partial<Pick<Context, 'logger' | 'getUnitKey' | 'allowOrphanRules'>>;
|
||||
type EvaluationFunction<Kind extends NodeKind = NodeKind> = (this: Engine, node: ASTNode & {
|
||||
nodeKind: Kind;
|
||||
}) => {
|
||||
nodeKind: Kind;
|
||||
} & EvaluatedNode;
|
||||
type ParsedRules<Name extends string> = Record<Name, RuleNode<Name>>;
|
||||
declare class Engine<Name extends string = string> {
|
||||
baseContext: Context<Name>;
|
||||
context: Context<string>;
|
||||
publicParsedRules: ParsedRules<Name>;
|
||||
cache: Cache;
|
||||
subEngines: Array<Engine<Name>>;
|
||||
subEngineId: number | undefined;
|
||||
constructor(rules?: RawPublicodes<Name>, options?: Options);
|
||||
resetCache(): void;
|
||||
setSituation(situation?: Partial<Record<Name, PublicodesExpression | ASTNode>>, options?: {
|
||||
keepPreviousSituation?: boolean;
|
||||
}): this;
|
||||
inversionFail(): boolean;
|
||||
getRule(dottedName: Name): ParsedRules<Name>[Name];
|
||||
getParsedRules(): ParsedRules<Name>;
|
||||
evaluate(value: PublicodesExpression): EvaluatedNode;
|
||||
evaluateNode<T extends ASTNode>(parsedNode: T): EvaluatedNode & T;
|
||||
/**
|
||||
* Shallow Engine instance copy. Keeps references to the original Engine instance attributes.
|
||||
*/
|
||||
shallowCopy(): Engine<Name>;
|
||||
private checkExperimentalRule;
|
||||
}
|
||||
|
||||
export { ASTNode, EvaluatedNode, Evaluation, EvaluationFunction, ExprAST, Logger, ParsedRules, PublicodesError, PublicodesExpression, Rule, RuleNode, Unit, capitalise0, Engine as default, formatValue, isPublicodesError, parseExpression, parsePublicodes, parseUnit, reduceAST, serializeEvaluation, serializeUnit, simplifyNodeUnit, makeASTTransformer as transformAST, traverseASTNode, ruleUtils as utils };
|
|
@ -0,0 +1,639 @@
|
|||
type ArrondiNode = {
|
||||
explanation: {
|
||||
arrondi: ASTNode;
|
||||
valeur: ASTNode;
|
||||
};
|
||||
nodeKind: 'arrondi';
|
||||
};
|
||||
|
||||
type TrancheNode = {
|
||||
taux: ASTNode;
|
||||
} | {
|
||||
montant: ASTNode;
|
||||
};
|
||||
type TrancheNodes = Array<TrancheNode & {
|
||||
plafond?: ASTNode;
|
||||
isActive?: boolean;
|
||||
}>;
|
||||
|
||||
type BarèmeNode = {
|
||||
explanation: {
|
||||
tranches: TrancheNodes;
|
||||
multiplicateur: ASTNode;
|
||||
assiette: ASTNode;
|
||||
};
|
||||
nodeKind: 'barème';
|
||||
};
|
||||
|
||||
type ConditionNode = {
|
||||
explanation: {
|
||||
si: ASTNode;
|
||||
alors: ASTNode;
|
||||
sinon: ASTNode;
|
||||
};
|
||||
nodeKind: 'condition';
|
||||
};
|
||||
|
||||
type NodesTypes = WeakMap<ASTNode, InferedType>;
|
||||
type InferedType = {
|
||||
isNullable: boolean | undefined;
|
||||
} & Pick<ConstantNode, 'type'>;
|
||||
|
||||
type Rule = {
|
||||
formule?: Record<string, unknown> | string;
|
||||
valeur?: Record<string, unknown> | string;
|
||||
question?: string;
|
||||
description?: string;
|
||||
unité?: string;
|
||||
acronyme?: string;
|
||||
exemples?: any;
|
||||
résumé?: string;
|
||||
icônes?: string;
|
||||
titre?: string;
|
||||
sévérité?: string;
|
||||
type?: string;
|
||||
experimental?: 'oui';
|
||||
'possiblement non applicable'?: 'oui';
|
||||
privé?: 'oui';
|
||||
note?: string;
|
||||
remplace?: Remplace | Array<Remplace>;
|
||||
'rend non applicable'?: Remplace | Array<Remplace>;
|
||||
suggestions?: Record<string, string | number | Record<string, unknown>>;
|
||||
références?: {
|
||||
[source: string]: string;
|
||||
};
|
||||
API?: string;
|
||||
'identifiant court'?: string;
|
||||
} & Record<string, unknown>;
|
||||
type Remplace = {
|
||||
'références à': string;
|
||||
dans?: Array<string> | string;
|
||||
'sauf dans'?: Array<string> | string;
|
||||
priorité?: number;
|
||||
} | string;
|
||||
type RuleNode<Name extends string = string> = {
|
||||
dottedName: Name;
|
||||
title: string;
|
||||
nodeKind: 'rule';
|
||||
virtualRule: boolean;
|
||||
private: boolean;
|
||||
rawNode: Rule;
|
||||
replacements: Array<ReplacementRule>;
|
||||
explanation: {
|
||||
valeur: ASTNode;
|
||||
parents: Array<ASTNode>;
|
||||
nullableParent?: ASTNode;
|
||||
ruleDisabledByItsParent: boolean;
|
||||
};
|
||||
suggestions: Record<string, ASTNode>;
|
||||
'identifiant court'?: string;
|
||||
};
|
||||
|
||||
type ReplacementRule = {
|
||||
nodeKind: 'replacementRule';
|
||||
definitionRule: ASTNode<'reference'> & {
|
||||
dottedName: string;
|
||||
};
|
||||
replacedReference: ASTNode<'reference'>;
|
||||
priority?: number;
|
||||
whiteListedNames: Array<ASTNode<'reference'>>;
|
||||
rawNode: any;
|
||||
blackListedNames: Array<ASTNode<'reference'>>;
|
||||
remplacementRuleId: number;
|
||||
replaceByNonApplicable: boolean;
|
||||
};
|
||||
|
||||
type getUnitKey = (writtenUnit: string) => string;
|
||||
type formatUnit = (unit: string, count: number) => string;
|
||||
declare const parseUnit: (string: string, getUnitKey?: getUnitKey) => Unit;
|
||||
declare function serializeUnit(rawUnit: Unit | undefined | string, count?: number, formatUnit?: formatUnit): string | undefined;
|
||||
|
||||
type Context<RuleNames extends string = string> = {
|
||||
dottedName: RuleNames | '';
|
||||
parsedRules: ParsedRules<RuleNames>;
|
||||
nodesTypes: NodesTypes;
|
||||
referencesMaps: ReferencesMaps<RuleNames>;
|
||||
rulesReplacements: RulesReplacements<RuleNames>;
|
||||
getUnitKey?: getUnitKey;
|
||||
logger: Logger;
|
||||
inversionMaxIterations?: number;
|
||||
/**
|
||||
* Don't throw an error if the parent of a rule is not found.
|
||||
* This is useful to parse partial rule sets (e.g. optimized ones).
|
||||
*/
|
||||
allowOrphanRules: boolean;
|
||||
/**
|
||||
* This is used to generate unique IDs for sub-engines, we need to generate them at
|
||||
* */
|
||||
subEngineIncrementingNumber?: number;
|
||||
};
|
||||
type RulesReplacements<RuleNames extends string> = Partial<Record<RuleNames, ReplacementRule[]>>;
|
||||
type ReferencesMaps<Names extends string> = {
|
||||
referencesIn: Map<Names, Set<Names>>;
|
||||
rulesThatUse: Map<Names, Set<Names>>;
|
||||
};
|
||||
type RawRule = Omit<Rule, 'nom'> | string | number | null;
|
||||
type RawPublicodes<RuleNames extends string> = Partial<Record<RuleNames, RawRule>>;
|
||||
declare function parsePublicodes<ContextNames extends string, NewRulesNames extends string>(rawRules: RawPublicodes<NewRulesNames>, partialContext?: Partial<Context<ContextNames>>): Pick<Context<ContextNames | NewRulesNames>, 'parsedRules' | 'nodesTypes' | 'referencesMaps' | 'rulesReplacements'>;
|
||||
|
||||
type ReferenceNode = {
|
||||
nodeKind: 'reference';
|
||||
name: string;
|
||||
contextDottedName: string;
|
||||
dottedName?: string;
|
||||
title?: string;
|
||||
acronym?: string;
|
||||
};
|
||||
|
||||
type ContextNode = {
|
||||
explanation: {
|
||||
valeur: ASTNode;
|
||||
contexte: Array<[ReferenceNode, ASTNode]>;
|
||||
subEngineId: number;
|
||||
};
|
||||
nodeKind: 'contexte';
|
||||
};
|
||||
|
||||
type DuréeNode = {
|
||||
explanation: {
|
||||
depuis: ASTNode;
|
||||
"jusqu'à": ASTNode;
|
||||
};
|
||||
unit: Unit;
|
||||
nodeKind: 'durée';
|
||||
};
|
||||
|
||||
type EstNonDéfiniNode = {
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'est non défini';
|
||||
};
|
||||
|
||||
type EstNonApplicableNode = {
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'est non applicable';
|
||||
};
|
||||
|
||||
type GrilleNode = {
|
||||
explanation: {
|
||||
assiette: ASTNode;
|
||||
multiplicateur: ASTNode;
|
||||
tranches: TrancheNodes;
|
||||
};
|
||||
nodeKind: 'grille';
|
||||
};
|
||||
|
||||
type InversionNode = {
|
||||
explanation: {
|
||||
ruleToInverse: string;
|
||||
inversionCandidates: Array<ReferenceNode>;
|
||||
unit?: Unit;
|
||||
inversionGoal?: ASTNode;
|
||||
numberOfIteration?: number;
|
||||
inversionFail?: boolean;
|
||||
};
|
||||
nodeKind: 'inversion';
|
||||
};
|
||||
|
||||
type PossibilityNode = {
|
||||
explanation: Array<ASTNode>;
|
||||
'choix obligatoire'?: 'oui' | 'non';
|
||||
context: string;
|
||||
nodeKind: 'une possibilité';
|
||||
};
|
||||
|
||||
declare const knownOperations: {
|
||||
readonly '*': readonly [(a: any, b: any) => number, "×"];
|
||||
readonly '/': readonly [(a: any, b: any) => number, "∕"];
|
||||
readonly '+': readonly [(a: any, b: any) => any];
|
||||
readonly '-': readonly [(a: any, b: any) => number, "−"];
|
||||
readonly '<': readonly [(a: any, b: any) => boolean];
|
||||
readonly '<=': readonly [(a: any, b: any) => boolean, "≤"];
|
||||
readonly '>': readonly [(a: any, b: any) => boolean];
|
||||
readonly '>=': readonly [(a: any, b: any) => boolean, "≥"];
|
||||
readonly '=': readonly [(a: any, b: any) => boolean];
|
||||
readonly '!=': readonly [(a: any, b: any) => boolean, "≠"];
|
||||
readonly et: readonly [(a: any, b: any) => any];
|
||||
readonly ou: readonly [(a: any, b: any) => any];
|
||||
};
|
||||
type OperationNode = {
|
||||
nodeKind: 'operation';
|
||||
explanation: [ASTNode, ASTNode];
|
||||
operationKind: keyof typeof knownOperations;
|
||||
operator: string;
|
||||
};
|
||||
|
||||
type RésoudreRéférenceCirculaireNode = {
|
||||
explanation: {
|
||||
ruleToSolve: string;
|
||||
valeur: ASTNode;
|
||||
};
|
||||
nodeKind: 'résoudre référence circulaire';
|
||||
};
|
||||
|
||||
type SimplifierUnitéNode = {
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'simplifier unité';
|
||||
};
|
||||
|
||||
type TauxProgressifNode = {
|
||||
explanation: {
|
||||
tranches: TrancheNodes;
|
||||
multiplicateur: ASTNode;
|
||||
assiette: ASTNode;
|
||||
};
|
||||
nodeKind: 'taux progressif';
|
||||
};
|
||||
|
||||
declare const NAME: "texte";
|
||||
type TexteNode = {
|
||||
explanation: Array<ASTNode | string>;
|
||||
nodeKind: typeof NAME;
|
||||
};
|
||||
|
||||
type UnitéNode = {
|
||||
unit: Unit;
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'unité';
|
||||
};
|
||||
|
||||
type VariableManquanteNode = {
|
||||
missingVariable: string;
|
||||
explanation: ASTNode;
|
||||
nodeKind: 'variable manquante';
|
||||
};
|
||||
|
||||
type VariationNode = {
|
||||
explanation: Array<{
|
||||
condition: ASTNode;
|
||||
consequence: ASTNode;
|
||||
satisfied?: boolean;
|
||||
}>;
|
||||
nodeKind: 'variations';
|
||||
};
|
||||
|
||||
type ConstantNode = {
|
||||
type: 'boolean' | 'number' | 'string' | 'date' | undefined;
|
||||
nodeValue: Evaluation;
|
||||
nodeKind: 'constant';
|
||||
isNullable?: boolean;
|
||||
isDefault?: boolean;
|
||||
fullPrecision?: boolean;
|
||||
};
|
||||
type PossibleNodes = RuleNode | ReferenceNode | ArrondiNode | BarèmeNode | DuréeNode | GrilleNode | EstNonApplicableNode | EstNonDéfiniNode | InversionNode | OperationNode | PossibilityNode | ContextNode | SimplifierUnitéNode | RésoudreRéférenceCirculaireNode | TauxProgressifNode | UnitéNode | VariationNode | ConditionNode | ConstantNode | ReplacementRule | VariableManquanteNode | TexteNode;
|
||||
type NodeKind = PossibleNodes['nodeKind'];
|
||||
type ASTNode<N extends NodeKind = NodeKind> = PossibleNodes & {
|
||||
nodeKind: N;
|
||||
isDefault?: boolean;
|
||||
sourceMap?: {
|
||||
mecanismName: string;
|
||||
args: Record<string, ASTNode | Array<ASTNode>>;
|
||||
};
|
||||
rawNode?: string | Record<string, unknown>;
|
||||
} & (EvaluationDecoration<Types> | {});
|
||||
type ASTTransformer = (n: ASTNode) => ASTNode;
|
||||
type TraverseFunction<K extends NodeKind> = (fn: ASTTransformer, node: ASTNode<K>) => ASTNode<K>;
|
||||
type BaseUnit = string;
|
||||
type Unit = {
|
||||
numerators: Array<BaseUnit>;
|
||||
denominators: Array<BaseUnit>;
|
||||
};
|
||||
type EvaluationDecoration<T extends Types> = {
|
||||
nodeValue: Evaluation<T>;
|
||||
unit?: Unit;
|
||||
traversedVariables?: Array<string>;
|
||||
missingVariables: MissingVariables;
|
||||
};
|
||||
type Types = number | boolean | string | Record<string, unknown>;
|
||||
type Evaluation<T extends Types = Types> = T | null | undefined;
|
||||
type EvaluatedNode<K extends NodeKind = NodeKind, T extends Types = Types> = EvaluationDecoration<T> & ASTNode<K>;
|
||||
type MissingVariables = Record<string, number>;
|
||||
|
||||
type GraphCycles = string[][];
|
||||
type RawRules = Parameters<typeof parsePublicodes>[0];
|
||||
/**
|
||||
* This function is useful so as to print the dependencies at each node of the
|
||||
* cycle.
|
||||
* ⚠️ Indeed, the findCycles function returns the cycle found using the
|
||||
* Tarjan method, which is **not necessarily the smallest cycle**. However, the
|
||||
* smallest cycle is more readable.
|
||||
*/
|
||||
declare function cyclicDependencies(rawRules: RawRules): [GraphCycles, string[]];
|
||||
|
||||
/**
|
||||
* Returns the last part of a dottedName (the leaf).
|
||||
*/
|
||||
declare const nameLeaf: (dottedName: string) => string;
|
||||
/**
|
||||
* Encodes a dottedName for the URL to be secure.
|
||||
* @see {@link decodeRuleName}
|
||||
*/
|
||||
declare const encodeRuleName: (dottedName: string) => string;
|
||||
/**
|
||||
* Decodes an encoded dottedName.
|
||||
* @see {@link encodeRuleName}
|
||||
*/
|
||||
declare const decodeRuleName: (dottedName: string) => string;
|
||||
/**
|
||||
* Return dottedName from contextName
|
||||
*/
|
||||
declare const contextNameToDottedName: (contextName: string) => string;
|
||||
/**
|
||||
* Returns the parent dottedName
|
||||
*/
|
||||
declare const ruleParent: (dottedName: string) => string;
|
||||
/**
|
||||
* Returns an array of dottedName from near parent to far parent.
|
||||
*/
|
||||
declare function ruleParents(dottedName: string): Array<string>;
|
||||
/**
|
||||
* Returns an array of all child rules of a dottedName
|
||||
*/
|
||||
declare const getChildrenRules: (parsedRules: ParsedRules<string>, dottedName: string) => string[];
|
||||
/**
|
||||
* Finds the common ancestor of two dottedName
|
||||
*/
|
||||
declare function findCommonAncestor(dottedName1: string, dottedName2: string): string;
|
||||
/**
|
||||
* Check wether a rule is accessible from a namespace.
|
||||
*
|
||||
* Takes into account that some namespace can be `private`, i.e. that they can only be
|
||||
* accessed by immediate parent, children or siblings.
|
||||
*
|
||||
* @param rules The parsed rules
|
||||
* @param contextName The context of the call
|
||||
* @param name The namespace checked for accessibility
|
||||
*/
|
||||
declare function isAccessible(rules: Record<string, RuleNode>, contextName: string, name: string): boolean;
|
||||
/**
|
||||
* Check wether a rule is tagged as experimental.
|
||||
*
|
||||
* Takes into account the a children of an experimental rule is also experimental
|
||||
*
|
||||
* @param rules The parsed rules
|
||||
* @param name The namespace checked for experimental
|
||||
*/
|
||||
declare function isExperimental(rules: Record<string, RuleNode>, name: string): boolean;
|
||||
declare function disambiguateReference<R extends Record<string, RuleNode>>(rules: R, referencedFrom: string | undefined, partialName: string): keyof R;
|
||||
declare function ruleWithDedicatedDocumentationPage(rule: any): boolean;
|
||||
declare function updateReferencesMapsFromReferenceNode(node: ASTNode, referencesMaps: ReferencesMaps<string>, ruleDottedName?: string): void;
|
||||
declare function disambiguateReferenceNode(node: ASTNode, parsedRules: ParsedRules<string>): ReferenceNode | undefined;
|
||||
|
||||
declare const ruleUtils_contextNameToDottedName: typeof contextNameToDottedName;
|
||||
declare const ruleUtils_cyclicDependencies: typeof cyclicDependencies;
|
||||
declare const ruleUtils_decodeRuleName: typeof decodeRuleName;
|
||||
declare const ruleUtils_disambiguateReference: typeof disambiguateReference;
|
||||
declare const ruleUtils_disambiguateReferenceNode: typeof disambiguateReferenceNode;
|
||||
declare const ruleUtils_encodeRuleName: typeof encodeRuleName;
|
||||
declare const ruleUtils_findCommonAncestor: typeof findCommonAncestor;
|
||||
declare const ruleUtils_getChildrenRules: typeof getChildrenRules;
|
||||
declare const ruleUtils_isAccessible: typeof isAccessible;
|
||||
declare const ruleUtils_isExperimental: typeof isExperimental;
|
||||
declare const ruleUtils_nameLeaf: typeof nameLeaf;
|
||||
declare const ruleUtils_ruleParent: typeof ruleParent;
|
||||
declare const ruleUtils_ruleParents: typeof ruleParents;
|
||||
declare const ruleUtils_ruleWithDedicatedDocumentationPage: typeof ruleWithDedicatedDocumentationPage;
|
||||
declare const ruleUtils_updateReferencesMapsFromReferenceNode: typeof updateReferencesMapsFromReferenceNode;
|
||||
declare namespace ruleUtils {
|
||||
export {
|
||||
ruleUtils_contextNameToDottedName as contextNameToDottedName,
|
||||
ruleUtils_cyclicDependencies as cyclicDependencies,
|
||||
ruleUtils_decodeRuleName as decodeRuleName,
|
||||
ruleUtils_disambiguateReference as disambiguateReference,
|
||||
ruleUtils_disambiguateReferenceNode as disambiguateReferenceNode,
|
||||
ruleUtils_encodeRuleName as encodeRuleName,
|
||||
ruleUtils_findCommonAncestor as findCommonAncestor,
|
||||
ruleUtils_getChildrenRules as getChildrenRules,
|
||||
ruleUtils_isAccessible as isAccessible,
|
||||
ruleUtils_isExperimental as isExperimental,
|
||||
ruleUtils_nameLeaf as nameLeaf,
|
||||
ruleUtils_ruleParent as ruleParent,
|
||||
ruleUtils_ruleParents as ruleParents,
|
||||
ruleUtils_ruleWithDedicatedDocumentationPage as ruleWithDedicatedDocumentationPage,
|
||||
ruleUtils_updateReferencesMapsFromReferenceNode as updateReferencesMapsFromReferenceNode,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
This function creates a transormation of the AST from on a simpler
|
||||
callback function `fn`
|
||||
|
||||
`fn` will be called with the nodes of the ASTTree during the exploration
|
||||
|
||||
The outcome of the callback function has an influence on the exploration of the AST :
|
||||
- `false`, the node is not updated and the exploration does not continue further down this branch
|
||||
- `undefined`, the node is not updated but the exploration continues and its children will be transformed
|
||||
- `ASTNode`, the node is transformed to the new value and the exploration does not continue further down the branch
|
||||
|
||||
`updateFn` : It is possible to specifically use the updated version of a child
|
||||
by using the function passed as second argument. The returned value will be the
|
||||
transformed version of the node.
|
||||
*/
|
||||
declare function makeASTTransformer(fn: (node: ASTNode, transform: ASTTransformer) => ASTNode | undefined | false, stopOnUpdate?: boolean): ASTTransformer;
|
||||
/**
|
||||
* This function allows to construct a specific value while exploring the AST with
|
||||
* a simple reducing function as argument.
|
||||
*
|
||||
* `fn` will be called with the currently reduced value `acc` and the current node of the AST
|
||||
*
|
||||
* If the callback function returns:
|
||||
* - `undefined`, the exploration continues further down and all the children are reduced
|
||||
* successively to a single value
|
||||
* - `T`, the reduced value is returned
|
||||
*
|
||||
* `reduceFn` : It is possible to specifically use the reduced value of a child
|
||||
* by using the function passed as second argument. The returned value will be the reduced version
|
||||
* of the node
|
||||
*/
|
||||
declare function reduceAST<T>(fn: (acc: T, n: ASTNode, reduceFn: (n: ASTNode) => T) => T | undefined, start: T, node: ASTNode): T;
|
||||
/**
|
||||
* Apply a transform function on children. Not recursive.
|
||||
*/
|
||||
declare const traverseASTNode: TraverseFunction<NodeKind>;
|
||||
|
||||
/**
|
||||
* Each error name with corresponding type in info value
|
||||
*/
|
||||
interface PublicodesErrorTypes {
|
||||
InternalError: {
|
||||
dottedName?: string;
|
||||
};
|
||||
EngineError: Record<string, never>;
|
||||
SyntaxError: {
|
||||
dottedName: string;
|
||||
};
|
||||
EvaluationError: {
|
||||
dottedName: string;
|
||||
};
|
||||
UnknownRule: {
|
||||
dottedName: string;
|
||||
};
|
||||
PrivateRule: {
|
||||
dottedName: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Return true if `error` is a PublicodesError,
|
||||
* use `name` parameter to check and narow error type
|
||||
* @example
|
||||
* try {
|
||||
* new Engine().evaluate()
|
||||
* } catch (error) {
|
||||
* if (isPublicodesError(error, 'EngineError')) {
|
||||
* console.log(error.info)
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
declare const isPublicodesError: <Name extends keyof PublicodesErrorTypes>(error: unknown, name?: Name | undefined) => error is PublicodesError<Name | undefined extends undefined ? keyof PublicodesErrorTypes : Name>;
|
||||
/**
|
||||
* Generic error for Publicodes
|
||||
*/
|
||||
declare class PublicodesError<Name extends keyof PublicodesErrorTypes> extends Error {
|
||||
name: Name;
|
||||
info: PublicodesErrorTypes[Name];
|
||||
constructor(name: Name, message: string, info: PublicodesErrorTypes[Name], originalError?: Error);
|
||||
}
|
||||
|
||||
declare function capitalise0(name: undefined): undefined;
|
||||
declare function capitalise0(name: string): string;
|
||||
type Options$1 = {
|
||||
language?: string;
|
||||
displayedUnit?: string;
|
||||
precision?: number;
|
||||
formatUnit?: formatUnit;
|
||||
};
|
||||
declare function formatValue(value: number | {
|
||||
nodeValue: Evaluation;
|
||||
unit?: Unit;
|
||||
} | undefined, { language, displayedUnit, formatUnit, precision }?: Options$1): any;
|
||||
|
||||
declare function simplifyNodeUnit(node: any): any;
|
||||
|
||||
type BinaryOp = {
|
||||
'+': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'-': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'*': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'/': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'>': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'<': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'>=': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'<=': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'=': [ExprAST, ExprAST];
|
||||
} | {
|
||||
'!=': [ExprAST, ExprAST];
|
||||
};
|
||||
type UnaryOp = {
|
||||
'-': [{
|
||||
value: 0;
|
||||
}, ExprAST];
|
||||
};
|
||||
/** AST of a publicodes expression. */
|
||||
type ExprAST = BinaryOp | UnaryOp | {
|
||||
variable: string;
|
||||
} | {
|
||||
constant: {
|
||||
type: 'number';
|
||||
nodeValue: number;
|
||||
};
|
||||
unité?: string;
|
||||
} | {
|
||||
constant: {
|
||||
type: 'boolean';
|
||||
nodeValue: boolean;
|
||||
};
|
||||
} | {
|
||||
constant: {
|
||||
type: 'string' | 'date';
|
||||
nodeValue: string;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse a publicodes expression into an JSON object representing the AST.
|
||||
*
|
||||
* The parsing is done with the [nearley](https://nearley.js.org/) parser
|
||||
*
|
||||
* @param rawNode The expression to parse
|
||||
* @param dottedName The dottedName of the rule being parsed
|
||||
*
|
||||
* @returns The parsing result as a JSON object
|
||||
*
|
||||
* @throws A `SyntaxError` if the expression is invalid
|
||||
* @throws A `PublicodesInternalError` if the parser is unable to parse the expression
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* parseExpression('20.3 * nombre', 'foo . bar')
|
||||
* // returns { "*": [ { constant: { type: "number", nodeValue: 20.3 } }, { variable:"nombre" } ] }
|
||||
* ```
|
||||
*/
|
||||
declare function parseExpression(rawNode: string, dottedName: string): ExprAST;
|
||||
|
||||
declare function serializeEvaluation(node: EvaluatedNode): string | undefined;
|
||||
|
||||
type Cache = {
|
||||
inversionFail?: boolean;
|
||||
_meta: {
|
||||
evaluationRuleStack: Array<string>;
|
||||
parentRuleStack: Array<string>;
|
||||
currentContexteSituation?: string;
|
||||
};
|
||||
/**
|
||||
* Every time we encounter a reference to a rule in an expression we add it
|
||||
* to the current Set of traversed variables. Because we evaluate the
|
||||
* expression graph “top to bottom” (ie. we start by the high-level goal and
|
||||
* recursively evaluate its dependencies), we need to handle rule
|
||||
* “boundaries”, so that when we “enter” in the evaluation of a dependency,
|
||||
* we start with a clear empty set of traversed variables. Then, when we go
|
||||
* back to the referencer rule, we need to add all to merge the two sets :
|
||||
* rules already traversed in the current expression and the one from the
|
||||
* reference.
|
||||
*/
|
||||
traversedVariablesStack?: Array<Set<string>>;
|
||||
nodes: Map<PublicodesExpression | ASTNode, EvaluatedNode>;
|
||||
};
|
||||
|
||||
type PublicodesExpression = string | Record<string, unknown> | number;
|
||||
type Logger = {
|
||||
log(message: string): void;
|
||||
warn(message: string): void;
|
||||
error(message: string): void;
|
||||
};
|
||||
type Options = Partial<Pick<Context, 'logger' | 'getUnitKey' | 'allowOrphanRules'>>;
|
||||
type EvaluationFunction<Kind extends NodeKind = NodeKind> = (this: Engine, node: ASTNode & {
|
||||
nodeKind: Kind;
|
||||
}) => {
|
||||
nodeKind: Kind;
|
||||
} & EvaluatedNode;
|
||||
type ParsedRules<Name extends string> = Record<Name, RuleNode<Name>>;
|
||||
declare class Engine<Name extends string = string> {
|
||||
baseContext: Context<Name>;
|
||||
context: Context<string>;
|
||||
publicParsedRules: ParsedRules<Name>;
|
||||
cache: Cache;
|
||||
subEngines: Array<Engine<Name>>;
|
||||
subEngineId: number | undefined;
|
||||
constructor(rules?: RawPublicodes<Name>, options?: Options);
|
||||
resetCache(): void;
|
||||
setSituation(situation?: Partial<Record<Name, PublicodesExpression | ASTNode>>, options?: {
|
||||
keepPreviousSituation?: boolean;
|
||||
}): this;
|
||||
inversionFail(): boolean;
|
||||
getRule(dottedName: Name): ParsedRules<Name>[Name];
|
||||
getParsedRules(): ParsedRules<Name>;
|
||||
evaluate(value: PublicodesExpression): EvaluatedNode;
|
||||
evaluateNode<T extends ASTNode>(parsedNode: T): EvaluatedNode & T;
|
||||
/**
|
||||
* Shallow Engine instance copy. Keeps references to the original Engine instance attributes.
|
||||
*/
|
||||
shallowCopy(): Engine<Name>;
|
||||
private checkExperimentalRule;
|
||||
}
|
||||
|
||||
export { ASTNode, EvaluatedNode, Evaluation, EvaluationFunction, ExprAST, Logger, ParsedRules, PublicodesError, PublicodesExpression, Rule, RuleNode, Unit, capitalise0, Engine as default, formatValue, isPublicodesError, parseExpression, parsePublicodes, parseUnit, reduceAST, serializeEvaluation, serializeUnit, simplifyNodeUnit, makeASTTransformer as transformAST, traverseASTNode, ruleUtils as utils };
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"name": "publicodes",
|
||||
"version": "1.2.1",
|
||||
"description": "A declarative language for encoding public algorithm",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"require": "./dist/index.cjs",
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/publicodes/publicodes.git",
|
||||
"directory": "packages/core"
|
||||
},
|
||||
"bugs": "https://github.com/publicodes/publicodes/issues",
|
||||
"homepage": "https://publi.codes/",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@rushstack/package-deps-hash": "^3.2.67",
|
||||
"@types/chai": "^4.3.6",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/sinon-chai": "^3.2.10",
|
||||
"chai": "^4.3.8",
|
||||
"dedent-js": "1.0.1",
|
||||
"intl": "^1.2.5",
|
||||
"mitata": "^0.1.6",
|
||||
"mocha": "^9.2.2",
|
||||
"modele-social": "^2.0.0",
|
||||
"moo": "^0.5.2",
|
||||
"nearley": "^2.20.1",
|
||||
"sinon": "^12.0.1",
|
||||
"sinon-chai": "^3.7.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsup": "^7.2.0",
|
||||
"typescript": "^5.2.2",
|
||||
"yaml": "^2.3.2"
|
||||
},
|
||||
"scripts": {
|
||||
"codegen": "nearleyc ./src/grammar.ne -o ./src/grammar.codegen.js",
|
||||
"build": "tsup",
|
||||
"dev": "tsup --watch",
|
||||
"test:type": "tsc --noEmit",
|
||||
"test": "mocha \"./test/**/*.test.{js,ts}\"",
|
||||
"bench": "tsup --entry.bench ./bench/index.ts && node ./dist/bench.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/mocha": "^9.0.0"
|
||||
}
|
||||
}
|
|
@ -74,7 +74,7 @@
|
|||
"markdown-to-jsx": "^7.3.2",
|
||||
"modele-social": "workspace:^",
|
||||
"piano-analytics-js": "^6.13.0",
|
||||
"publicodes": "^1.2.0",
|
||||
"publicodes": "file:../publicodes",
|
||||
"react": "^18.2.0",
|
||||
"react-aria": "^3.24.0",
|
||||
"react-day-picker": "^8.8.2",
|
||||
|
|
22
yarn.lock
22
yarn.lock
|
@ -26926,6 +26926,24 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"publicodes@file:../publicodes::locator=site%40workspace%3Asite":
|
||||
version: 1.2.1
|
||||
resolution: "publicodes@file:../publicodes#../publicodes::hash=7d6a6c&locator=site%40workspace%3Asite"
|
||||
peerDependencies:
|
||||
"@types/mocha": ^9.0.0
|
||||
checksum: 3785b3864b10ef292c3a23d7b1a8358a73dd3b423e8e96c3d357e8e99a0a674ca634c34a606eec3ed252a1ebc82d61d08fa51c876527a91f6beb6bc71f2ede80
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"publicodes@file:./publicodes::locator=root%40workspace%3A.":
|
||||
version: 1.2.1
|
||||
resolution: "publicodes@file:./publicodes#./publicodes::hash=7d6a6c&locator=root%40workspace%3A."
|
||||
peerDependencies:
|
||||
"@types/mocha": ^9.0.0
|
||||
checksum: 3785b3864b10ef292c3a23d7b1a8358a73dd3b423e8e96c3d357e8e99a0a674ca634c34a606eec3ed252a1ebc82d61d08fa51c876527a91f6beb6bc71f2ede80
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"publicodes@npm:^1.1.1, publicodes@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "publicodes@npm:1.2.0"
|
||||
|
@ -28642,7 +28660,7 @@ __metadata:
|
|||
eslint-plugin-vitest: ^0.3.22
|
||||
optics-ts: ^2.4.1
|
||||
prettier: ^3.0.3
|
||||
publicodes: ^1.2.0
|
||||
publicodes: "file:./publicodes"
|
||||
rimraf: ^5.0.1
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
@ -29272,7 +29290,7 @@ __metadata:
|
|||
modele-social: "workspace:^"
|
||||
netlify-cli: ^17.10.1
|
||||
piano-analytics-js: ^6.13.0
|
||||
publicodes: ^1.2.0
|
||||
publicodes: "file:../publicodes"
|
||||
react: ^18.2.0
|
||||
react-aria: ^3.24.0
|
||||
react-day-picker: ^8.8.2
|
||||
|
|
Loading…
Reference in New Issue