airtable-ts
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -5,5 +5,2 @@ "use strict"; | ||
const typeUtils_1 = require("./mapping/typeUtils"); | ||
// In theory, this should never catch stuff because our type mapping logic should | ||
// verify the types are compatible. However, "In theory there is no difference | ||
// between theory and practice - in practice there is" | ||
/** | ||
@@ -10,0 +7,0 @@ * In theory, this should never catch stuff because our type mapping logic should |
@@ -20,9 +20,13 @@ "use strict"; | ||
string: { | ||
url: fallbackMapperPair('', ''), | ||
email: fallbackMapperPair('', ''), | ||
phoneNumber: fallbackMapperPair('', ''), | ||
singleLineText: fallbackMapperPair('', ''), | ||
email: fallbackMapperPair('', ''), | ||
url: fallbackMapperPair('', ''), | ||
multilineText: fallbackMapperPair('', ''), | ||
richText: fallbackMapperPair('', ''), | ||
phoneNumber: fallbackMapperPair('', ''), | ||
singleSelect: fallbackMapperPair('', ''), | ||
externalSyncSource: { | ||
toAirtable: () => { throw new Error('[airtable-ts] externalSyncSource type field is readonly'); }, | ||
fromAirtable: (value) => value ?? '', | ||
}, | ||
multipleSelects: { | ||
@@ -56,2 +60,18 @@ toAirtable: (value) => { | ||
}, | ||
date: { | ||
toAirtable: (value) => { | ||
const date = new Date(value); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date string'); | ||
} | ||
return date.toJSON().slice(0, 10); | ||
}, | ||
fromAirtable: (value) => { | ||
const date = new Date(value ?? ''); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date string'); | ||
} | ||
return date.toJSON(); | ||
}, | ||
}, | ||
dateTime: { | ||
@@ -74,12 +94,12 @@ toAirtable: (value) => { | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (!value) { | ||
throw new Error('[airtable-ts] Failed to coerce multipleLookupValues type field to a single string, as it was blank'); | ||
throw new Error('[airtable-ts] Failed to coerce lookup type field to a single string, as it was blank'); | ||
} | ||
if (value.length !== 1) { | ||
throw new Error(`[airtable-ts] Can't coerce multipleLookupValues to a single string, as there were ${value?.length} entries`); | ||
throw new Error(`[airtable-ts] Can't coerce lookup to a single string, as there were ${value?.length} entries`); | ||
} | ||
if (typeof value[0] !== 'string') { | ||
throw new Error(`[airtable-ts] Can't coerce singular multipleLookupValues to a single string, as it was of type ${typeof value[0]}`); | ||
throw new Error(`[airtable-ts] Can't coerce singular lookup to a single string, as it was of type ${typeof value[0]}`); | ||
} | ||
@@ -89,11 +109,35 @@ return value[0]; | ||
}, | ||
rollup: { | ||
toAirtable: () => { throw new Error('[airtable-ts] rollup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'string') | ||
return value; | ||
if (value === undefined || value === null) | ||
return ''; | ||
throw new Error(`[airtable-ts] Can't coerce rollup to a string, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
formula: { | ||
toAirtable: () => { throw new Error('[airtable-ts] formula type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'string') | ||
return value; | ||
if (value === undefined || value === null) | ||
return ''; | ||
throw new Error(`[airtable-ts] Can't coerce formula to a string, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
}, | ||
'string | null': { | ||
url: fallbackMapperPair(null, null), | ||
email: fallbackMapperPair(null, null), | ||
phoneNumber: fallbackMapperPair(null, null), | ||
singleLineText: fallbackMapperPair(null, null), | ||
email: fallbackMapperPair(null, null), | ||
url: fallbackMapperPair(null, null), | ||
multilineText: fallbackMapperPair(null, null), | ||
richText: fallbackMapperPair(null, null), | ||
phoneNumber: fallbackMapperPair(null, null), | ||
singleSelect: fallbackMapperPair(null, null), | ||
externalSyncSource: { | ||
toAirtable: () => { throw new Error('[airtable-ts] externalSyncSource type field is readonly'); }, | ||
fromAirtable: (value) => value ?? null, | ||
}, | ||
multipleSelects: { | ||
@@ -127,2 +171,22 @@ toAirtable: (value) => { | ||
}, | ||
date: { | ||
toAirtable: (value) => { | ||
if (value === null) | ||
return null; | ||
const date = new Date(value); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date'); | ||
} | ||
return date.toJSON().slice(0, 10); | ||
}, | ||
fromAirtable: (value) => { | ||
if (value === null || value === undefined) | ||
return null; | ||
const date = new Date(value); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date'); | ||
} | ||
return date.toJSON(); | ||
}, | ||
}, | ||
dateTime: { | ||
@@ -149,3 +213,3 @@ toAirtable: (value) => { | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
@@ -156,6 +220,6 @@ if (!value || value.length === 0) { | ||
if (value.length !== 1) { | ||
throw new Error(`[airtable-ts] Can't coerce multipleLookupValues to a single string, as there were ${value?.length} entries`); | ||
throw new Error(`[airtable-ts] Can't coerce lookup to a single string, as there were ${value?.length} entries`); | ||
} | ||
if (typeof value[0] !== 'string') { | ||
throw new Error(`[airtable-ts] Can't coerce singular multipleLookupValues to a single string, as it was of type ${typeof value[0]}`); | ||
throw new Error(`[airtable-ts] Can't coerce singular lookup to a single string, as it was of type ${typeof value[0]}`); | ||
} | ||
@@ -165,2 +229,22 @@ return value[0]; | ||
}, | ||
rollup: { | ||
toAirtable: () => { throw new Error('[airtable-ts] rollup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'string') | ||
return value; | ||
if (value === undefined || value === null) | ||
return null; | ||
throw new Error(`[airtable-ts] Can't coerce rollup to a string, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
formula: { | ||
toAirtable: () => { throw new Error('[airtable-ts] formula type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'string') | ||
return value; | ||
if (value === undefined || value === null) | ||
return null; | ||
throw new Error(`[airtable-ts] Can't coerce formula to a string, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
}, | ||
@@ -170,12 +254,12 @@ boolean: { | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (!value) { | ||
throw new Error('[airtable-ts] Failed to coerce multipleLookupValues type field to a single boolean, as it was blank'); | ||
throw new Error('[airtable-ts] Failed to coerce lookup type field to a single boolean, as it was blank'); | ||
} | ||
if (value.length !== 1) { | ||
throw new Error(`[airtable-ts] Can't coerce multipleLookupValues to a single boolean, as there were ${value?.length} entries`); | ||
throw new Error(`[airtable-ts] Can't coerce lookup to a single boolean, as there were ${value?.length} entries`); | ||
} | ||
if (typeof value[0] !== 'boolean') { | ||
throw new Error(`[airtable-ts] Can't coerce singular multipleLookupValues to a single boolean, as it was of type ${typeof value[0]}`); | ||
throw new Error(`[airtable-ts] Can't coerce singular lookup to a single boolean, as it was of type ${typeof value[0]}`); | ||
} | ||
@@ -189,3 +273,3 @@ return value[0]; | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
@@ -196,6 +280,6 @@ if (!value || value.length === 0) { | ||
if (value.length !== 1) { | ||
throw new Error(`[airtable-ts] Can't coerce multipleLookupValues to a single boolean, as there were ${value?.length} entries`); | ||
throw new Error(`[airtable-ts] Can't coerce lookup to a single boolean, as there were ${value?.length} entries`); | ||
} | ||
if (typeof value[0] !== 'boolean') { | ||
throw new Error(`[airtable-ts] Can't coerce singular multipleLookupValues to a single boolean, as it was of type ${typeof value[0]}`); | ||
throw new Error(`[airtable-ts] Can't coerce singular lookup to a single boolean, as it was of type ${typeof value[0]}`); | ||
} | ||
@@ -208,6 +292,6 @@ return value[0]; | ||
number: requiredMapperPair, | ||
percent: requiredMapperPair, | ||
currency: requiredMapperPair, | ||
rating: requiredMapperPair, | ||
duration: requiredMapperPair, | ||
currency: requiredMapperPair, | ||
percent: requiredMapperPair, | ||
count: { | ||
@@ -222,2 +306,19 @@ toAirtable: () => { throw new Error('[airtable-ts] count type field is readonly'); }, | ||
// Number assumed to be unix time in seconds | ||
date: { | ||
toAirtable: (value) => { | ||
const date = new Date(value * 1000); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date'); | ||
} | ||
return date.toJSON().slice(0, 10); | ||
}, | ||
fromAirtable: (value) => { | ||
const date = new Date(value ?? ''); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date'); | ||
} | ||
return Math.floor(date.getTime() / 1000); | ||
}, | ||
}, | ||
// Number assumed to be unix time in seconds | ||
dateTime: { | ||
@@ -240,12 +341,12 @@ toAirtable: (value) => { | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (!value) { | ||
throw new Error('[airtable-ts] Failed to coerce multipleLookupValues type field to a single number, as it was blank'); | ||
throw new Error('[airtable-ts] Failed to coerce lookup type field to a single number, as it was blank'); | ||
} | ||
if (value.length !== 1) { | ||
throw new Error(`[airtable-ts] Can't coerce multipleLookupValues to a single number, as there were ${value?.length} entries`); | ||
throw new Error(`[airtable-ts] Can't coerce lookup to a single number, as there were ${value?.length} entries`); | ||
} | ||
if (typeof value[0] !== 'number') { | ||
throw new Error(`[airtable-ts] Can't coerce singular multipleLookupValues to a single number, as it was of type ${typeof value[0]}`); | ||
throw new Error(`[airtable-ts] Can't coerce singular lookup to a single number, as it was of type ${typeof value[0]}`); | ||
} | ||
@@ -255,9 +356,25 @@ return value[0]; | ||
}, | ||
rollup: { | ||
toAirtable: () => { throw new Error('[airtable-ts] rollup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'number') | ||
return value; | ||
throw new Error(`[airtable-ts] Can't coerce rollup to a number, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
formula: { | ||
toAirtable: () => { throw new Error('[airtable-ts] formula type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'number') | ||
return value; | ||
throw new Error(`[airtable-ts] Can't coerce formula to a number, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
}, | ||
'number | null': { | ||
number: fallbackMapperPair(null, null), | ||
percent: fallbackMapperPair(null, null), | ||
currency: fallbackMapperPair(null, null), | ||
rating: fallbackMapperPair(null, null), | ||
duration: fallbackMapperPair(null, null), | ||
currency: fallbackMapperPair(null, null), | ||
percent: fallbackMapperPair(null, null), | ||
count: { | ||
@@ -272,2 +389,23 @@ fromAirtable: (value) => value ?? null, | ||
// Number assumed to be unix time in seconds | ||
date: { | ||
toAirtable: (value) => { | ||
if (value === null) | ||
return null; | ||
const date = new Date(value * 1000); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date'); | ||
} | ||
return date.toJSON().slice(0, 10); | ||
}, | ||
fromAirtable: (value) => { | ||
if (value === null || value === undefined) | ||
return null; | ||
const date = new Date(value); | ||
if (Number.isNaN(date.getTime())) { | ||
throw new Error('[airtable-ts] Invalid date'); | ||
} | ||
return Math.floor(date.getTime() / 1000); | ||
}, | ||
}, | ||
// Number assumed to be unix time in seconds | ||
dateTime: { | ||
@@ -294,3 +432,3 @@ toAirtable: (value) => { | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
@@ -301,6 +439,6 @@ if (!value || value.length === 0) { | ||
if (value.length !== 1) { | ||
throw new Error(`[airtable-ts] Can't coerce multipleLookupValues to a single number, as there were ${value?.length} entries`); | ||
throw new Error(`[airtable-ts] Can't coerce lookup to a single number, as there were ${value?.length} entries`); | ||
} | ||
if (typeof value[0] !== 'number') { | ||
throw new Error(`[airtable-ts] Can't coerce singular multipleLookupValues to a single number, as it was of type ${typeof value[0]}`); | ||
throw new Error(`[airtable-ts] Can't coerce singular lookup to a single number, as it was of type ${typeof value[0]}`); | ||
} | ||
@@ -310,2 +448,22 @@ return value[0]; | ||
}, | ||
rollup: { | ||
toAirtable: () => { throw new Error('[airtable-ts] rollup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'number') | ||
return value; | ||
if (value === null || value === undefined) | ||
return null; | ||
throw new Error(`[airtable-ts] Can't coerce rollup to a number, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
formula: { | ||
toAirtable: () => { throw new Error('[airtable-ts] formula type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (typeof value === 'number') | ||
return value; | ||
if (value === null || value === undefined) | ||
return null; | ||
throw new Error(`[airtable-ts] Can't coerce formula to a number, as it was of type ${typeof value}`); | ||
}, | ||
}, | ||
}, | ||
@@ -316,9 +474,9 @@ 'string[]': { | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (!Array.isArray(value)) { | ||
throw new Error('[airtable-ts] Failed to coerce multipleLookupValues type field to a string array, as it was not an array'); | ||
throw new Error('[airtable-ts] Failed to coerce lookup type field to a string array, as it was not an array'); | ||
} | ||
if (value.some((v) => typeof v !== 'string')) { | ||
throw new Error('[airtable-ts] Can\'t coerce multipleLookupValues to a string array, as it had non string type'); | ||
throw new Error('[airtable-ts] Can\'t coerce lookup to a string array, as it had non string type'); | ||
} | ||
@@ -328,2 +486,14 @@ return value; | ||
}, | ||
formula: { | ||
toAirtable: () => { throw new Error('[airtable-ts] formula type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (!Array.isArray(value)) { | ||
throw new Error('[airtable-ts] Failed to coerce formula type field to a string array, as it was not an array'); | ||
} | ||
if (value.some((v) => typeof v !== 'string')) { | ||
throw new Error('[airtable-ts] Can\'t coerce formula to a string array, as it had non string type'); | ||
} | ||
return value; | ||
}, | ||
}, | ||
}, | ||
@@ -334,3 +504,3 @@ 'string[] | null': { | ||
multipleLookupValues: { | ||
toAirtable: () => { throw new Error('[airtable-ts] multipleLookupValues type field is readonly'); }, | ||
toAirtable: () => { throw new Error('[airtable-ts] lookup type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
@@ -341,6 +511,6 @@ if (!value && !Array.isArray(value)) { | ||
if (!Array.isArray(value)) { | ||
throw new Error('[airtable-ts] Failed to coerce multipleLookupValues type field to a string array, as it was not an array'); | ||
throw new Error('[airtable-ts] Failed to coerce lookup type field to a string array, as it was not an array'); | ||
} | ||
if (value.some((v) => typeof v !== 'string')) { | ||
throw new Error('[airtable-ts] Can\'t coerce multipleLookupValues to a string array, as it had non string type'); | ||
throw new Error('[airtable-ts] Can\'t coerce lookup to a string array, as it had non string type'); | ||
} | ||
@@ -350,3 +520,18 @@ return value; | ||
}, | ||
formula: { | ||
toAirtable: () => { throw new Error('[airtable-ts] formula type field is readonly'); }, | ||
fromAirtable: (value) => { | ||
if (!value && !Array.isArray(value)) { | ||
return null; | ||
} | ||
if (!Array.isArray(value)) { | ||
throw new Error('[airtable-ts] Failed to coerce formula type field to a string array, as it was not an array'); | ||
} | ||
if (value.some((v) => typeof v !== 'string')) { | ||
throw new Error('[airtable-ts] Can\'t coerce formula to a string array, as it had non string type'); | ||
} | ||
return value; | ||
}, | ||
}, | ||
}, | ||
}; |
@@ -5,4 +5,4 @@ export type TsTypeString = NonNullToString<any> | ToTsTypeString<any>; | ||
export type FromTsTypeString<T> = T extends 'string' ? string : T extends 'string | null' ? string | null : T extends 'number' ? number : T extends 'number | null' ? number | null : T extends 'boolean' ? boolean : T extends 'boolean | null' ? boolean | null : T extends 'string[]' ? string[] : T extends 'string[] | null' ? string[] | null : T extends 'number[]' ? number[] : T extends 'number[] | null' ? number[] | null : T extends 'boolean[]' ? boolean[] : T extends 'boolean[] | null' ? boolean[] | null : never; | ||
export type AirtableTypeString = 'singleLineText' | 'email' | 'url' | 'multilineText' | 'phoneNumber' | 'singleSelect' | 'checkbox' | 'number' | 'percent' | 'currency' | 'count' | 'autoNumber' | 'rating' | 'richText' | 'duration' | 'multipleRecordLinks' | 'multipleSelects' | 'dateTime' | 'multipleLookupValues'; | ||
export type FromAirtableTypeString<T> = null | (T extends 'singleLineText' ? string : T extends 'email' ? string : T extends 'url' ? string : T extends 'multilineText' ? string : T extends 'richText' ? string : T extends 'phoneNumber' ? string : T extends 'singleSelect' ? string : T extends 'checkbox' ? boolean : T extends 'number' ? number : T extends 'percent' ? number : T extends 'currency' ? number : T extends 'rating' ? number : T extends 'duration' ? number : T extends 'count' ? number : T extends 'autoNumber' ? number : T extends 'multipleRecordLinks' ? string[] : T extends 'multipleSelects' ? string[] : T extends 'multipleLookupValues' ? FromAirtableTypeString<any>[] : T extends 'dateTime' ? string : never); | ||
export type AirtableTypeString = 'aiText' | 'autoNumber' | 'barcode' | 'button' | 'checkbox' | 'count' | 'createdBy' | 'createdTime' | 'currency' | 'date' | 'dateTime' | 'duration' | 'email' | 'externalSyncSource' | 'formula' | 'lastModifiedBy' | 'lastModifiedTime' | 'lookup' | 'multipleLookupValues' | 'multilineText' | 'multipleAttachments' | 'multipleCollaborators' | 'multipleRecordLinks' | 'multipleSelects' | 'number' | 'percent' | 'phoneNumber' | 'rating' | 'richText' | 'rollup' | 'singleCollaborator' | 'singleLineText' | 'singleSelect' | 'url'; | ||
export type FromAirtableTypeString<T extends AirtableTypeString> = null | (T extends 'url' | 'email' | 'phoneNumber' | 'singleLineText' | 'multilineText' | 'richText' | 'singleSelect' | 'externalSyncSource' | 'date' | 'dateTime' | 'createdTime' | 'lastModifiedTime' ? string : T extends 'multipleRecordLinks' | 'multipleSelects' ? string[] : T extends 'number' | 'rating' | 'duration' | 'currency' | 'percent' | 'count' | 'autoNumber' ? number : T extends 'checkbox' ? boolean : T extends 'lookup' | 'multipleLookupValues' | 'rollup' | 'formula' ? FromAirtableTypeString<any>[] : never); | ||
/** | ||
@@ -9,0 +9,0 @@ * Verifies whether the given value is assignable to the given type |
{ | ||
"name": "airtable-ts", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "A type-safe Airtable SDK", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
61421
1227