@evidence-dev/component-utilities
Advanced tools
Comparing version 1.1.0 to 2.0.0-usql.0
# @evidence-dev/component-utilities | ||
## 2.0.0-usql.0 | ||
### Major Changes | ||
- cb0fc468: This update includes major changes to the way Evidence interacts with data. | ||
Instead of running queries against the production database, and including it | ||
with the project as pre-rendered, static JSON data; those queries are now stored as .parquet files. | ||
.parquet enables the use of DuckDB on the client, allowing for much greater levels of interactivity | ||
on pages, and interoperability between different data sources (e.g. joins across postgres & mysql). | ||
## 1.1.0 | ||
@@ -4,0 +15,0 @@ |
{ | ||
"name": "@evidence-dev/component-utilities", | ||
"version": "1.1.0", | ||
"version": "2.0.0-usql.0", | ||
"description": "", | ||
@@ -12,5 +12,2 @@ "main": "index.js", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"vitest": "^0.31.1" | ||
}, | ||
"type": "module", | ||
@@ -25,2 +22,5 @@ "dependencies": { | ||
}, | ||
"devDependencies": { | ||
"vitest": "^0.31.1" | ||
}, | ||
"scripts": { | ||
@@ -27,0 +27,0 @@ "test": "vitest --run", |
@@ -30,3 +30,3 @@ import ssf from 'ssf'; | ||
let matchingFormat = [...BUILT_IN_FORMATS, ...customFormats].find( | ||
(format) => format.formatTag?.toLowerCase() === potentialFormatTag?.toLowerCase() | ||
(format) => format.formatTag?.toLowerCase() === potentialFormatTag?.toLowerCase?.() | ||
); | ||
@@ -60,3 +60,3 @@ if (matchingFormat) { | ||
let matchingFormat = [...BUILT_IN_FORMATS, ...customFormats].find( | ||
(format) => format.formatTag?.toLowerCase() === potentialFormatTag?.toLowerCase() | ||
(format) => format.formatTag?.toLowerCase() === potentialFormatTag?.toLowerCase?.() | ||
); | ||
@@ -63,0 +63,0 @@ let newFormat = {}; |
@@ -6,2 +6,6 @@ import inferColumnTypes from './inferColumnTypes'; | ||
if (data) { | ||
if (data._evidenceColumnTypes) { | ||
let columnTypes = data._evidenceColumnTypes; | ||
return columnTypes.find((item) => item.name?.toLowerCase() === column?.toLowerCase()); | ||
} | ||
if (Array.isArray(data) && data.length > 0) { | ||
@@ -8,0 +12,0 @@ item = data[0]; |
@@ -5,9 +5,8 @@ import { tidy, summarize, min, max, median } from '@tidyjs/tidy'; | ||
* | ||
* @param {*} data | ||
* @param {*} column | ||
* @returns undefined if not all the defined values are numbers | ||
* @param {Record<string, unknown>[]} data | ||
* @param {string} columnName | ||
* @returns {{ min?: number, max?: number, median?: number, maxDecimals: number, unitType: string }} | ||
*/ | ||
export function getColumnUnitSummary(data, columnName) { | ||
let seriesSummary; | ||
let seriesExtents = tidy( | ||
const seriesExtents = tidy( | ||
data, | ||
@@ -18,5 +17,5 @@ summarize({ min: min(columnName), max: max(columnName), median: median(columnName) }) | ||
//TODO try to use summerize spec in tidy | ||
let { maxDecimals, unitType } = summarizeUnits(data.map((row) => row[columnName])); | ||
const { maxDecimals, unitType } = summarizeUnits(data.map((row) => row[columnName])); | ||
seriesSummary = { | ||
return { | ||
min: seriesExtents.min, | ||
@@ -28,21 +27,21 @@ max: seriesExtents.max, | ||
}; | ||
return seriesSummary; | ||
} | ||
/** | ||
* | ||
* @param {Record<string, unknown>[]} data | ||
* @param {string} column | ||
* @returns {[number?, number?]} | ||
*/ | ||
export function getColumnExtentsLegacy(data, column) { | ||
var domainData = tidy(data, summarize({ min: min(column), max: max(column) })); | ||
let minValue = domainData[0].min; | ||
let maxValue = domainData[0].max; | ||
return [minValue, maxValue]; | ||
const domainData = tidy(data, summarize({ min: min(column), max: max(column) }))[0]; | ||
return [domainData.min, domainData.max]; | ||
} | ||
/** | ||
* | ||
* @param {number[]} series | ||
* @returns {{ maxDecimals: number, unitType: string }} | ||
*/ | ||
function summarizeUnits(series) { | ||
let undefinedCount = 0; | ||
let nullCount = 0; | ||
let stringCount = 0; | ||
let numberCount = 0; | ||
let dateCount = 0; | ||
let objectCount = 0; | ||
let maxDecimals = 0; | ||
if (series === undefined || series === null || series.length === 0) { | ||
@@ -54,57 +53,16 @@ return { | ||
} else { | ||
for (let i = 0; i < series.length; i++) { | ||
let nextElement = series[i]; | ||
switch (typeof nextElement) { | ||
case 'undefined': | ||
undefinedCount++; | ||
break; | ||
case 'null': //typically this will be object | ||
nullCount++; | ||
break; | ||
case 'number': { | ||
numberCount++; | ||
let thisDecimalPlaces = nextElement.toString().split('.')[1]?.length; | ||
if (thisDecimalPlaces && thisDecimalPlaces > maxDecimals) { | ||
maxDecimals = thisDecimalPlaces; | ||
} | ||
break; | ||
} | ||
case 'string': | ||
stringCount++; | ||
break; | ||
case 'object': | ||
if (nextElement instanceof Date) { | ||
dateCount++; | ||
} else if (nextElement === null) { | ||
nullCount++; | ||
} else { | ||
objectCount++; | ||
} | ||
break; | ||
case 'date': | ||
dateCount++; | ||
break; | ||
case 'function': | ||
default: | ||
break; | ||
let maxDecimals = 0; | ||
for (const element of series) { | ||
const decimal_places = element?.toString().split('.')[1]?.length; | ||
if (decimal_places > maxDecimals) { | ||
maxDecimals = decimal_places; | ||
} | ||
} | ||
let unitType = undefined; | ||
let emptyValueCount = undefinedCount + nullCount; | ||
if (numberCount + emptyValueCount === series.length) { | ||
unitType = 'number'; | ||
} else if (stringCount + emptyValueCount === series.length) { | ||
unitType = 'string'; | ||
} else if (dateCount + emptyValueCount === series.length) { | ||
unitType = 'date'; | ||
} else if (objectCount + emptyValueCount === series.length) { | ||
unitType = 'object'; | ||
} else { | ||
unitType = 'unknown'; | ||
} | ||
return { | ||
maxDecimals: maxDecimals, | ||
unitType: unitType | ||
unitType: 'number' | ||
}; | ||
} | ||
} |
import getColumnEvidenceType from './getColumnEvidenceType.js'; | ||
import { getColumnExtentsLegacy, getColumnUnitSummary } from './getColumnExtents.js'; | ||
import { lookupColumnFormat } from './formatting'; | ||
import { getColumnUnitSummary } from './getColumnExtents.js'; | ||
import { lookupColumnFormat } from './formatting.js'; | ||
import formatTitle from './formatTitle.js'; | ||
/** | ||
* @typedef {Object} ColumnSummary | ||
* @property {string} title | ||
* @property {string} type | ||
* @property {Object} evidenceColumnType | ||
* @property {ReturnType<typeof lookupColumnFormat>} format | ||
* @property {ReturnType<typeof getColumnUnitSummary>} columnUnitSummary | ||
*/ | ||
/** | ||
* @function | ||
* @template T | ||
* @param {Record<string, unknown>[]} data | ||
* @param {T} returnType | ||
* @returns {T extends 'object' ? Record<string, ColumnSummary> : (ColumnSummary & { id: string })[]} | ||
*/ | ||
export default function getColumnSummary(data, returnType = 'object') { | ||
var colName; | ||
var colType; | ||
var evidenceColumnType; | ||
var colFormat; | ||
let columnUnitSummary; | ||
let columnSummary = []; | ||
/** @type {Record<string, ColumnSummary>} */ | ||
const columnSummary = {}; | ||
var colExtentsLegacy; | ||
for (const colName of Object.keys(data[0])) { | ||
const evidenceColumnType = getColumnEvidenceType(data, colName); | ||
const type = evidenceColumnType.evidenceType; | ||
const columnUnitSummary = | ||
evidenceColumnType.evidenceType === 'number' | ||
? getColumnUnitSummary(data, colName) | ||
: { | ||
maxDecimals: 0, | ||
unitType: evidenceColumnType.evidenceType | ||
}; | ||
const format = lookupColumnFormat(colName, evidenceColumnType, columnUnitSummary); | ||
if (returnType === 'object') { | ||
for (const [key] of Object.entries(data[0])) { | ||
colName = key; | ||
evidenceColumnType = getColumnEvidenceType(data, colName); | ||
colType = evidenceColumnType.evidenceType; | ||
columnUnitSummary = getColumnUnitSummary(data, colName); | ||
colFormat = lookupColumnFormat(key, evidenceColumnType, columnUnitSummary); | ||
colExtentsLegacy = getColumnExtentsLegacy(data, colName); | ||
columnSummary[colName] = { | ||
title: formatTitle(colName, format), | ||
type, | ||
evidenceColumnType, | ||
format, | ||
columnUnitSummary | ||
}; | ||
} | ||
let thisCol = { | ||
[colName]: { | ||
title: formatTitle(colName, colFormat), | ||
type: colType, | ||
evidenceColumnType: evidenceColumnType, | ||
format: colFormat, | ||
columnUnitSummary: columnUnitSummary, | ||
extentsLegacy: colExtentsLegacy | ||
} | ||
}; | ||
columnSummary = { ...columnSummary, ...thisCol }; | ||
} | ||
} else { | ||
for (const [key] of Object.entries(data[0])) { | ||
colName = key; | ||
evidenceColumnType = getColumnEvidenceType(data, colName); | ||
colType = evidenceColumnType.evidenceType; | ||
columnUnitSummary = getColumnUnitSummary(data, colName); | ||
colFormat = lookupColumnFormat(key, evidenceColumnType, columnUnitSummary); | ||
colExtentsLegacy = getColumnExtentsLegacy(data, colName); | ||
columnSummary.push({ | ||
id: colName, | ||
title: formatTitle(colName, colFormat), | ||
type: colType, | ||
evidenceColumnType: evidenceColumnType, | ||
format: colFormat, | ||
columnUnitSummary: columnUnitSummary, | ||
extentsLegacy: colExtentsLegacy | ||
}); | ||
} | ||
if (returnType !== 'object') { | ||
return Object.entries(columnSummary).map(([key, value]) => ({ id: key, ...value })); | ||
} | ||
@@ -57,0 +50,0 @@ |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
176223
6462
2
1