{"_id":"@adiba-banking-cloud/filter-builder","_rev":"2-4ec6b472f0853a046f0b0f83727afe5a","name":"@adiba-banking-cloud/filter-builder","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@adiba-banking-cloud/filter-builder","version":"0.1.0","keywords":["odata","filter","query-builder"],"license":"ISC","_id":"@adiba-banking-cloud/filter-builder@0.1.0","maintainers":[{"name":"xamuel98","email":"samuelakintomiwa98@gmail.com"},{"name":"adiba-creation-team","email":"devops@turog.ng"}],"dist":{"shasum":"94480ef50be328aaddc18a4b9e55eb640946b7fa","tarball":"https://registry.npmjs.org/@adiba-banking-cloud/filter-builder/-/filter-builder-0.1.0.tgz","fileCount":5,"integrity":"sha512-yMYj+PdfGvjHHPF0ggQjydzKqj4Jvxa5qfSofl5vQlprqDPXDAmfQJAbAxOFL9eoCGx6xCvEcneO5aTUP8SkHQ==","signatures":[{"sig":"MEQCIHDKeSccM5ZY91eQX+HVy5mh5dH73PbRONOB1S/852hyAiA6TAPpYUKh+XaL60H2w0ua9A2r3tgUulMJIpEcn1dWZQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3629},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.js","scripts":{"test":"npm run build && node --test test/**/*.test.mjs","build":"tsc -p tsconfig.json","clean":"rm -rf dist"},"_npmUser":{"name":"xamuel98","email":"samuelakintomiwa98@gmail.com"},"_npmVersion":"10.9.2","description":"Framework-agnostic OData filter builder utilities for ADIBA SDKs and apps","directories":{},"_nodeVersion":"22.13.0","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.6.3"},"_npmOperationalInternal":{"tmp":"tmp/filter-builder_0.1.0_1777994142679_0.44791763007083296","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@adiba-banking-cloud/filter-builder","version":"0.1.1","description":"Framework-agnostic OData filter builder utilities for ADIBA SDKs and apps","license":"ISC","type":"module","main":"dist/index.js","module":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc -p tsconfig.json","clean":"rm -rf dist","test":"npm run build && node --test test/**/*.test.mjs"},"keywords":["odata","filter","query-builder"],"devDependencies":{"typescript":"^5.6.3"},"_id":"@adiba-banking-cloud/filter-builder@0.1.1","_nodeVersion":"22.13.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-S+0lWkGDDoCcLoOd2n/E2H4aa1m1PSmV1J6+mC7isypHfDRvWABwEPVCQvf1wlr/yqHfe7rVKm1Vgpk5awJlwA==","shasum":"a97e890f552e4ec01914c9f2ac763b56074ce152","tarball":"https://registry.npmjs.org/@adiba-banking-cloud/filter-builder/-/filter-builder-0.1.1.tgz","fileCount":6,"unpackedSize":10012,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIC/wzOff1fy4Vtd1zvjIyM6IzzA6awkSffGmE2l0QMozAiAjTfhFyK1VfPL6X7ApB2MsXUv/p4ycSYgTHHTw5Bdu+g=="}]},"_npmUser":{"name":"xamuel98","email":"samuelakintomiwa98@gmail.com"},"directories":{},"maintainers":[{"name":"xamuel98","email":"samuelakintomiwa98@gmail.com"},{"name":"adiba-creation-team","email":"devops@turog.ng"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/filter-builder_0.1.1_1777998021596_0.5466331763194086"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-05T15:15:42.435Z","modified":"2026-05-05T16:20:21.877Z","0.1.0":"2026-05-05T15:15:42.817Z","0.1.1":"2026-05-05T16:20:21.738Z"},"license":"ISC","keywords":["odata","filter","query-builder"],"description":"Framework-agnostic OData filter builder utilities for ADIBA SDKs and apps","maintainers":[{"name":"xamuel98","email":"samuelakintomiwa98@gmail.com"},{"name":"adiba-creation-team","email":"devops@turog.ng"}],"readme":"# @adiba-banking-cloud/filter-builder\n\nFramework-agnostic OData filter builder utilities for ADIBA SDKs and apps.\n\nThis package helps you build OData-style filter expressions such as:\n\n```text\npartyName eq 'Patrica' and status eq 'ACTIVE' and age ge 10\n```\n\nIt is intentionally small:\n\n- no React dependencies\n- no SDK-specific assumptions\n- no built-in URL construction\n\nThe package builds the filter expression only. The calling package is responsible for encoding it and attaching it to a request.\n\n## Install\n\n```bash\nnpm install @adiba-banking-cloud/filter-builder\n```\n\n## Exports\n\n- `buildODataFilter(...)`\n- `and(...)`\n- `or(...)`\n\n## When To Use\n\nUse this package when:\n\n- your backend expects OData-style filter expressions\n- you want a typed way to build rules like `eq`, `ge`, `contains`, and grouped conditions\n- you want to reuse filter-building logic across SDKs and apps\n\nDo not use this package when:\n\n- your backend expects plain query params like `status=ACTIVE&type=Organization`\n- your backend uses a different filter syntax\n- you want a package that constructs the full request URL for you\n\n## Core API\n\n### `buildODataFilter(input, options?)`\n\nBuilds an OData filter expression from either:\n\n- an array of rules\n- a grouped condition created with `and(...)` or `or(...)`\n\nTop-level arrays use `and` by default.\n\n```ts\nbuildODataFilter(rules);\nbuildODataFilter(rules, { topLevelLogic: \"or\" });\n```\n\n### `and(...filters)`\n\nCreates a grouped `and` expression.\n\n### `or(...filters)`\n\nCreates a grouped `or` expression.\n\n## Quick Start\n\n```ts\nimport { buildODataFilter } from \"@adiba-banking-cloud/filter-builder\";\n\nconst filter = buildODataFilter([\n  { field: \"partyName\", operator: \"eq\", value: \"Patrica\" },\n  { field: \"status\", operator: \"eq\", value: \"ACTIVE\" },\n  { field: \"age\", operator: \"ge\", value: 10 },\n]);\n\n// partyName eq 'Patrica' and status eq 'ACTIVE' and age ge 10\n```\n\nReturned value:\n\n```ts\n\"partyName eq 'Patrica' and status eq 'ACTIVE' and age ge 10\"\n```\n\n## Using In A URL\n\nThis package returns a plain filter expression. If you are sending it in a URL, encode it yourself:\n\n```ts\nimport { buildODataFilter } from \"@adiba-banking-cloud/filter-builder\";\n\nconst expression = buildODataFilter([\n  { field: \"status\", operator: \"eq\", value: \"ACTIVE\" },\n  { field: \"type\", operator: \"eq\", value: \"Organization\" },\n]);\n\nconst url = `/re/clients?filter=${encodeURIComponent(expression)}`;\n```\n\nResulting expression:\n\n```ts\n\"status eq 'ACTIVE' and type eq 'Organization'\"\n```\n\n## Nested Groups\n\n```ts\nimport { and, buildODataFilter, or } from \"@adiba-banking-cloud/filter-builder\";\n\nconst filter = buildODataFilter(\n  and(\n    { field: \"status\", operator: \"eq\", value: \"ACTIVE\" },\n    or(\n      { field: \"partyName\", operator: \"contains\", value: \"pat\" },\n      { field: \"partyName\", operator: \"startswith\", value: \"tri\" },\n    ),\n  ),\n);\n\n// status eq 'ACTIVE' and (contains(partyName,'pat') or startswith(partyName,'tri'))\n```\n\n## Top-Level OR Example\n\n```ts\nimport { buildODataFilter } from \"@adiba-banking-cloud/filter-builder\";\n\nconst filter = buildODataFilter(\n  [\n    { field: \"status\", operator: \"eq\", value: \"ACTIVE\" },\n    { field: \"status\", operator: \"eq\", value: \"PENDING\" },\n  ],\n  { topLevelLogic: \"or\" },\n);\n\n// status eq 'ACTIVE' or status eq 'PENDING'\n```\n\n## Supported Operators\n\nComparison operators:\n\n- `eq`\n- `ne`\n- `gt`\n- `ge`\n- `lt`\n- `le`\n\nFunction operators:\n\n- `contains`\n- `startswith`\n- `endswith`\n\n## Value Handling\n\n- strings are wrapped in single quotes\n- single quotes inside strings are escaped\n- booleans become `true` / `false`\n- numbers are emitted as-is\n- `null` becomes `null`\n- `Date` values become ISO strings wrapped in single quotes\n\nExample:\n\n```ts\nimport { buildODataFilter } from \"@adiba-banking-cloud/filter-builder\";\n\nconst filter = buildODataFilter([\n  { field: \"partyName\", operator: \"eq\", value: \"O'Brian\" },\n  { field: \"isFavorite\", operator: \"eq\", value: true },\n  {\n    field: \"createdAt\",\n    operator: \"ge\",\n    value: new Date(\"2024-01-02T03:04:05.000Z\"),\n  },\n  { field: \"deletedAt\", operator: \"eq\", value: null },\n]);\n\n// partyName eq 'O''Brian' and isFavorite eq true and createdAt ge '2024-01-02T03:04:05.000Z' and deletedAt eq null\n```\n\n## Flat Object Mapping Example\n\nMany SDKs start with a flat filter object like this:\n\n```ts\nconst filters = {\n  status: \"ACTIVE\",\n  type: \"Organization\",\n};\n```\n\nThat object does not describe operators by itself, so the consuming package needs to decide how to map it.\n\nFor example, if every field should be treated as `eq`:\n\n```ts\nimport { buildODataFilter, type ODataRule } from \"@adiba-banking-cloud/filter-builder\";\n\nconst filters = {\n  status: \"ACTIVE\",\n  type: \"Organization\",\n};\n\nconst rules: ODataRule[] = Object.entries(filters).map(([field, value]) => ({\n  field,\n  operator: \"eq\",\n  value,\n}));\n\nconst expression = buildODataFilter(rules);\n\n// status eq 'ACTIVE' and type eq 'Organization'\n```\n\nThat mapping step is intentionally left to the consuming SDK or app, because different APIs may want different defaults.\n\n## SDK Example\n\n```ts\nimport { buildODataFilter, type ODataRule } from \"@adiba-banking-cloud/filter-builder\";\n\ntype ClientFilters = {\n  status?: string;\n  type?: string;\n  partyName?: string;\n};\n\nexport const buildClientFilter = (filters: ClientFilters): string => {\n  const rules: ODataRule[] = Object.entries(filters)\n    .filter(([, value]) => value !== undefined && value !== \"\")\n    .map(([field, value]) => ({\n      field,\n      operator: \"eq\",\n      value: value!,\n    }));\n\n  return buildODataFilter(rules);\n};\n```\n\nThen:\n\n```ts\nconst expression = buildClientFilter({\n  status: \"ACTIVE\",\n  type: \"Organization\",\n});\n\nconst url = `/re/clients?filter=${encodeURIComponent(expression)}`;\n```\n\n## Types\n\nThe package exports typed filter structures:\n\n- `ODataRule`\n- `ODataGroup`\n- `ODataNode`\n- `ODataOperator`\n- `ODataLogic`\n- `ODataFilterValue`\n\n## Notes\n\n- OData uses `ge` and `le`, not `gte` and `lte`\n- `buildODataFilter([...])` uses top-level `and` by default\n- this package returns only the filter expression, not the final URL\n- callers should use `encodeURIComponent(...)` before placing the expression in a query string\n- if you need custom SDK-specific mapping from flat objects to filter rules, build that in the consuming package and pass the resulting rules into `buildODataFilter(...)`\n","readmeFilename":"README.md"}