Gathering detailed insights and metrics for @bou-co/parsing
Gathering detailed insights and metrics for @bou-co/parsing
Gathering detailed insights and metrics for @bou-co/parsing
Gathering detailed insights and metrics for @bou-co/parsing
Toolkit for data manipulation, validation, type generation, and efficient query splitting. Perfect for handling complex data structures, ensuring data integrity, and generating TypeScript types dynamically.
npm install @bou-co/parsing
Typescript
Module System
Node Version
NPM Version
72
Supply Chain
98.8
Quality
93.6
Maintenance
100
Vulnerability
100
License
TypeScript (100%)
Total Downloads
2,323
Last Day
13
Last Week
315
Last Month
1,217
Last Year
2,323
MIT License
2 Stars
60 Commits
1 Watchers
2 Branches
1 Contributors
Updated on Jun 09, 2025
Minified
Minified + Gzipped
Latest Version
1.0.21
Package Id
@bou-co/parsing@1.0.21
Unpacked Size
35.06 kB
Size
11.08 kB
File Count
14
NPM Version
10.9.2
Node Version
22.13.1
Published on
Jun 09, 2025
Cumulative downloads
Total Downloads
Last Day
8.3%
13
Compared to previous day
Last Week
-23.7%
315
Compared to previous week
Last Month
130.5%
1,217
Compared to previous month
Last Year
0%
2,323
Compared to previous year
Bou Parsing is your ultimate sidekick for taming unruly data! Whether you're wrangling data from APIs, generating TypeScript types on the fly, or splitting complex queries into bite-sized pieces, Bou Parsing has got you covered. With its powerful yet easy-to-use functions, you can effortlessly manipulate, validate, and transform your data into exactly what you need. Say goodbye to tedious data handling and hello to a smoother, more efficient workflow with Bou Parsing!
1npm i @bou-co/parsing
1// parser-config.ts 2import { initializeParser } from '@bou-co/parsing'; 3 4export const { createParser } = initializeParser();
When querying data with an API that does not support picking what you want, createParser
function can be used to pick the data you need and remove the rest.
1import { createParser } from '../path-to/parser-config'; 2 3const rawDataFromApi = { 4 _id: 'abc-123', 5 title: 'Test', 6 description: 'Lorem ipsum', 7 priority: 1, 8}; 9 10const myParser = createParser({ 11 title: 'string', 12 description: 'string', 13 priority: 'number', 14}); 15 16const dataThatYouWanted = await myParser(rawDataFromApi);
In the example above we pick to get title, description and priority
but omit the _id
.
Note: value returned by createParser
is an async function as parsers do have a wide support for promises. For React.js component usage we have developed a client side hook useParserValue
to allow parser usage easily inside of React.js.
Rarely you can get good and easy type generation from external APIs (especially from CMS). With ParserReturnValue
it's possible to use your parser projection as the TypeScript type instead of writing the types on your own.
1import { ParserReturnValue } from '@bou-co/parsing'; 2import { createParser } from '../path-to/parser-config'; 3 4const myParser = createParser({ 5 title: 'string', 6 description: 'string', 7 priority: 'number', 8}); 9 10export type MyParserData = ParserReturnValue<typeof myParser>;
Type MyParserData
equals to:
1interface MyParserData { 2 title?: string; 3 description?: string; 4 priority?: number; 5}
Possible values that are automatically turned to types are string, number, boolean, object, any, unknown, undefined, date, array
or array<string etc.>
.
Note: @bou-co/parsing
type generation by default expects that any value can also be undefined!
It's also possible to use custom types for value with typed
function. With typed
you can pass any custom TypeScript values to be used as values generated with the typing.
1import { typed } from '@bou-co/parsing'; 2import { createParser } from '../path-to/parser-config'; 3 4interface Author { 5 name?: string; 6 title?: string; 7} 8 9const anotherParser = createParser({ 10 title: 'string', 11 category: typed<'blog' | 'news' | 'releases'>, 12 author: typed<Author>, 13}); 14 15export type AnotherParserData = ParserReturnValue<typeof anotherParser>;
In this case type AnotherParserData
equals to:
1interface AnotherParserData { 2 title?: string; 3 category?: 'blog' | 'news' | 'releases'; 4 author?: Author; 5}
With @bou-co/parsing
it's also possible to add values that are not part of the initial data.
1import { createParser } from '../path-to/parser-config'; 2 3const rawDataFromApi = { 4 _id: 'abc-123', 5 title: 'Test', 6 description: 'Lorem ipsum', 7 priority: 1, 8}; 9 10const BLOG_POST = 'blogPost'; 11 12const myParser = createParser({ 13 title: 'string', 14 description: 'string', 15 16 // 1. Static value added as is 17 postType: BLOG_POST 18 19 // 2. Function return value 20 randomNumber: () => Math.random() 21 22 // 3. Promises supported 23 asyncText: async () => { 24 const awaited = await fetch('your-api').then(res => res.text()) 25 return awaited; 26 } 27 28 // 4. Custom override for priority 29 priority: (context) => { 30 const { data } = context; 31 if (!data.priority) return 1; 32 return data.priority 33 } 34 35 // 5. Variation of raw value 36 metaTitle: (context) => { 37 const { data } = context; 38 if (!data.title) return 'Untitled blog post'; 39 return `${data.title} - Our blog` 40 } 41}); 42 43const dataThatYouWanted = await myParser(rawDataFromApi);
Note: When using functions to set data, you might need to manually define the type of the value that the function returns!
Good to know: The type of first argument (context) for any function is ParserContext
and it contains current raw data as "data" but also some information about the current parser!
Parsers can handle nested objects as properties defined in projection or as additional parsers.
1import { createParser } from '../path-to/parser-config'; 2 3const myParser = createParser({ 4 title: 'string', 5 nestedDataObject: { 6 description: 'string', 7 priority: 'number', 8 }, 9});
Adding '@array': true,
defines that projection inside of current level should be defined as array.
1import { createParser } from '../path-to/parser-config';
2
3const myParser = createParser({
4 title: 'string',
5 nestedDataArray: {
6 '@array': true,
7 description: 'string',
8 priority: 'number',
9 },
10});
1import { createParser } from '../path-to/parser-config';
2
3const innerParser = createParser({
4 description: 'string',
5 priority: 1,
6});
7
8const myParser = createParser({
9 title: 'string',
10 nestedDataObject: innerParser,
11 nestedDataArray: innerParser.asArray,
12});
Parsing supports fully conditional data picking and addition with @if
.
1import { createParser } from '../path-to/parser-config'; 2 3const myParser = createParser({ 4 title: 'string', 5 priority: 'number', 6 '@if': [ 7 // 1. Show description only if priority is 1 8 { 9 when: (context) => context.data.priority === 1, 10 then: { 11 description: 'string', 12 }, 13 }, 14 // 2. Omit description and add "highPriority: true" if priority is above 1 15 { 16 when: (context) => context.data.priority > 1, 17 then: { 18 highPriority: true, 19 }, 20 }, 21 // 3. Modify description and add "lowPriority: true" if priority is below 1 22 { 23 when: (context) => context.data.priority < 1, 24 then: { 25 lowPriority: true, 26 description: (context) => context.data.description + '?', 27 }, 28 }, 29 ], 30});
Adding data as individual property & value pairs is good when only few values are added but to manage larger additions you can use @combine
.
1import { createParser } from '../path-to/parser-config'; 2 3const rawDataFromApi = { 4 _id: 'abc-123', 5 title: 'Test', 6 description: 'Lorem ipsum', 7 priority: 1, 8}; 9 10const additionalDataParser = createParser({ 11 readCount: 'number', 12 likes: 'number', 13}); 14 15const myParser = createParser({ 16 title: 'string', 17 priority: 'number', 18 description: 'string', 19 '@combine': (context) => { 20 const { _id } = context.data; 21 const query = `your-api?id=${_id}`; 22 const rawAdditionalData = await fetch(query).then((res) => res.json()); 23 return additionalDataParser(rawAdditionalData); 24 }, 25}); 26 27const mergedData = await myParser(rawDataFromApi);
Variables in parsing are a way to easily edit string values that are coming from raw data. Variables can be used to easily add data about the build, render or current user.
To use variables anywhere, define them in your parsing config.
1// parser-config.ts 2import { initializeParser } from '@bou-co/parsing'; 3 4export const { createParser } = initializeParser(() => { 5 const currentYear = new Date().getFullYear(); 6 return { 7 currentYear, 8 }; 9});
After definition you can use them in the raw data.
1import { createParser } from '../path-to/parser-config'; 2 3const rawDataFromApi = { 4 title: 'Hello from {{currentYear}}', 5 description: 'Is the current year really {{currentYear}}?', 6}; 7 8const myParser = createParser({ 9 title: 'string', 10 description: 'string', 11}); 12 13const result = await myParser(rawDataFromApi);
Result in case above is:
1{ "title": "Hello from 2025", "description": "Is the current year really 2025?" }
1import { createParser } from '../path-to/parser-config'; 2 3const rawDataFromApi = { 4 title: 'Message for the whole {{entity}}', 5 description: 'Hello {{entity}}!', 6}; 7 8const myParser = createParser({ 9 title: 'string', 10 description: 'string', 11}); 12 13const instanceData = { 14 entity: 'world', 15}; 16 17const result = await myParser(rawDataFromApi, instanceData);
Result in case above is:
1{ "title": "Message for the whole world", "description": "Hello world!" }
For any variable provided in the data, there can be a fallback value in a form of another variable, string, number or boolean. Fallback values can be added with adding ||
after the initial variable and after that a secondary variable or just a value.
1import { createParser } from '../path-to/parser-config'; 2 3const rawDataFromApi = { 4 title: 'Message for the whole {{notFound || "city"}}', 5 description: 'Hello {{firstName || lastName || "Doe"}}!', 6 score: '{{score || 0}}', 7 active: '{{isActive || false}}', 8}; 9 10const myParser = createParser({ 11 title: 'string', 12 description: 'string', 13 score: 'number', 14 active: 'boolean', 15}); 16 17const instanceData = { 18 lastName: 'Johnson', 19}; 20 21const result = await myParser(rawDataFromApi, instanceData);
Result in case above is:
1{ 2 "title": "Message for the whole city", 3 "description": "Hello Johnson!", 4 "score": 0, 5 "active": false 6}
If you need to transform the value of a variable, you can do that with pipes. Pipes are useful for example when you want to transform an ISO date to something meant for humans. Pipes are defined in code as variables that are funtions and get the current variable value in the context as data. Pipes can also take in params that are then an array in the context.
1import { createParser } from '../path-to/parser-config'; 2 3const rawDataFromApi = { 4 title: 'Hello from {{title | uppercase}}', 5 publishedAt: 'This is published at {{date | toDateString}}', 6 score: '{{score | multiply:100 }}', // Add param for how much should the value be multiplied 7}; 8 9const myParser = createParser({ 10 title: 'string', 11 publishedAt: 'string', 12 score: 'number', 13}); 14 15const instanceData = { 16 // Variable values 17 title: 'the space', 18 publishedAt: '2025-05-22T12:00:00', 19 score: 0.42, 20 // Pipe functions (could most likely be added with initializeParser and not per instance) 21 uppercase: ({ data }) => data.toUpperCase(), 22 toDateString: ({ data }) => new Date(data).toLocaleString(), 23 multiply: ({ data, params: [by] = [2] }) => data * by, 24}; 25 26const result = await myParser(rawDataFromApi, instanceData);
Result in case above is:
1{ 2 "title": "Message for THE SPACE", 3 "publishedAt": "5/22/2025, 12:00:00 PM", 4 "score": 42 5}
No vulnerabilities found.
No security vulnerabilities found.