@tailor-platform/sdk 2.7.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/dist/{application-D5lh2-_W.mjs → application-D2E3FDfF.mjs} +2 -2
- package/dist/application-D2E3FDfF.mjs.map +1 -0
- package/dist/application-rySTKrFa.mjs +1 -0
- package/dist/cli/lib.mjs +1 -1
- package/dist/cli/main.mjs +45 -45
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/shared/seed-context.d.mts +3 -1
- package/dist/completion/zsh-worker.zsh +1 -1
- package/dist/configure/config/index.d.mts +2 -1
- package/dist/configure/index.d.mts +14 -14
- package/dist/configure/index.mjs +1 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/aigateway/index.d.mts +1 -3
- package/dist/configure/services/idp/index.d.mts +1 -1
- package/dist/configure/services/resolver/resolver.d.mts +1 -1
- package/dist/configure/services/tailordb/schema.d.mts +22 -13
- package/dist/configure/types/index.d.mts +1 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/plugin/types.d.mts +17 -7
- package/dist/register-ts-hook-D6aNriu3.mjs +642 -0
- package/dist/register-ts-hook-D6aNriu3.mjs.map +1 -0
- package/dist/{schema-AYG4OhXY.mjs → schema-6d_OHyZf.mjs} +2 -2
- package/dist/schema-6d_OHyZf.mjs.map +1 -0
- package/dist/{seed-DwqRFdqP.mjs → seed-CMkupmX8.mjs} +41 -17
- package/dist/seed-CMkupmX8.mjs.map +1 -0
- package/dist/types/helpers.d.mts +3 -1
- package/dist/vitest/index.d.mts +2 -2
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/pglite-kysely.d.mts +29 -7
- package/docs/plugin/custom.md +84 -0
- package/docs/services/executor.md +17 -0
- package/docs/services/idp.md +1 -1
- package/docs/services/resolver.md +1 -1
- package/docs/services/tailordb-migration.md +14 -8
- package/docs/services/tailordb.md +4 -0
- package/docs/services/workflow.md +1 -1
- package/package.json +13 -13
- package/dist/application-D5lh2-_W.mjs.map +0 -1
- package/dist/application-o09L68wE.mjs +0 -1
- package/dist/register-ts-hook-CL3Z3VP0.mjs +0 -642
- package/dist/register-ts-hook-CL3Z3VP0.mjs.map +0 -1
- package/dist/schema-AYG4OhXY.mjs.map +0 -1
- package/dist/seed-DwqRFdqP.mjs.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./brand-C8nMKhJC.mjs";import{cloneDeep as t}from"es-toolkit";const n={uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/,time:/^(?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d)$/,datetime:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d):(?<second>[0-5]\d|60)(\.(?<fraction>\d+))?(?<offset>[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/,decimal:/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/};function validateBaseValue(e){let{field:t,value:r,pathArray:i,issues:a}=e,o=i.length>0?i:void 0,s=a.length;switch(t.type){case`string`:typeof r!=`string`&&a.push({message:`Expected a string: received ${String(r)}`,path:o});break;case`integer`:(typeof r!=`number`||!Number.isInteger(r))&&a.push({message:`Expected an integer: received ${String(r)}`,path:o});break;case`float`:(typeof r!=`number`||!Number.isFinite(r))&&a.push({message:`Expected a number: received ${String(r)}`,path:o});break;case`boolean`:typeof r!=`boolean`&&a.push({message:`Expected a boolean: received ${String(r)}`,path:o});break;case`uuid`:(typeof r!=`string`||!n.uuid.test(r))&&a.push({message:`Expected a valid UUID: received ${String(r)}`,path:o});break;case`date`:(typeof r!=`string`||!n.date.test(r))&&a.push({message:`Expected to match "yyyy-MM-dd" format: received ${String(r)}`,path:o});break;case`datetime`:(typeof r!=`string`||!n.datetime.test(r))&&a.push({message:`Expected to match ISO format: received ${String(r)}`,path:o});break;case`time`:(typeof r!=`string`||!n.time.test(r))&&a.push({message:`Expected to match "HH:mm" format: received ${String(r)}`,path:o});break;case`decimal`:(typeof r!=`string`||!n.decimal.test(r))&&a.push({message:`Expected a decimal string: received ${String(r)}`,path:o});break;case`enum`:if(t._metadata.allowedValues){let e=t._metadata.allowedValues.map(e=>e.value);(typeof r!=`string`||!e.includes(r))&&a.push({message:`Must be one of [${e.join(`, `)}]: received ${String(r)}`,path:o})}break;case`nested`:{if(typeof r!=`object`||!r||Array.isArray(r)||r instanceof Date)return a.push({message:`Expected an object: received ${String(r)}`,path:o}),!1;let n=!0;for(let[a,o]of Object.entries(t.fields)){let t=r[a];validateBaseField({...e,field:o,value:t,pathArray:i.concat(a)})||(n=!1)}return n}}return a.length===s}function validateCustomValue(e,t){let{value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0;for(let e of t){let t=e({value:n});typeof t==`string`&&i.push({message:t,path:a})}}function validateBaseField(e){let{field:t,value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0,o=n==null;if(t._metadata.required&&o)return i.push({message:`Required field is missing`,path:a}),!1;if(!t._metadata.required&&o)return!0;let s=!0;if(t._metadata.array){if(!Array.isArray(n))return i.push({message:`Expected an array`,path:a}),!1;for(let t=0;t<n.length;t++)validateBaseValue({...e,value:n[t],pathArray:r.concat(`[${t}]`)})||(s=!1)}else s=validateBaseValue(e);return s}function validateCustomField(e){let{field:t,value:n,pathArray:r}=e;if(n==null)return;if(t.type===`nested`){let i=t._metadata.array?n:[n];for(let n=0;n<i.length;n++){let a=i[n],o=t._metadata.array?r.concat(`[${n}]`):r;for(let[n,r]of Object.entries(t.fields))validateCustomField({...e,field:r,value:a[n],pathArray:o.concat(n)})}}let i=t._metadata.validate;i?.length&&validateCustomValue(e,i)}function parseInternal(e){let{value:t}=e,n=[],r={...e,issues:n};return validateBaseField(r)&&validateCustomField(r),n.length>0?{issues:n}:{value:t??null}}function parseInputFields(e){let{fields:t,...n}=e;return parseInternal({...n,field:{type:`nested`,fields:t,_metadata:{required:!0}},pathArray:[]})}function mapAllowedValues(e){return e.map(e=>typeof e==`string`?{value:e,description:``}:{...e,description:e.description??``})}function createTailorDBField(e,t,n,r){return createTailorDBFieldRuntime(e,t,n,r)}function createTailorDBFieldRuntime(e,n,r,i){let a={required:!0},o;n&&(n.optional===!0&&(a.required=!1),n.array===!0&&(a.array=!0)),i&&(a.allowedValues=mapAllowedValues(i));function parseInternal$1(e){return parseInternal({...e,field:s})}function cloneWith(e){let t=s.clone();return Object.assign(t._metadata,e),t}let s={type:e,fields:r??{},_defined:void 0,_output:void 0,_metadata:a,get metadata(){return{...this._metadata}},get rawRelation(){return o?{...o,toward:{...o.toward}}:void 0},description(e){return cloneWith({description:e})},typeName(e){return cloneWith({typeName:e})},validate(...e){return cloneWith({validate:e})},parse(e){return parseInternal$1({value:e.value,data:e.data,invoker:e.invoker,pathArray:[]})},relation(e){let t=s.clone(),n=e.toward,r=`table`in n?n.table:n.type,i=r===`self`?`self`:r.name;return t._setRawRelation({type:e.type,toward:{table:i,as:e.toward.as,key:e.toward.key},backward:e.backward}),t},index(){return cloneWith({index:!0})},unique(){return cloneWith({unique:!0,index:!0})},vector(){return cloneWith({vector:!0})},default(e){return cloneWith({default:e})},hooks(e){return cloneWith({hooks:e})},serial(e){return cloneWith({serial:e})},clone(a){if(this._metadata.validate?.length&&a?.array!==void 0&&a.array!==(this._metadata.array===!0))throw Error(`Cannot change the array option on a field with custom validation`);let s=r;if(r){let e={};for(let[t,n]of Object.entries(r))e[t]=n.clone();s=e}let c=createTailorDBFieldRuntime(e,n,s,i);return Object.assign(c._metadata,t(this._metadata)),a&&(a.optional!==void 0&&(c._metadata.required=!a.optional),a.array!==void 0&&(c._metadata.array=a.array)),o&&c._setRawRelation(t(o)),c},_setRawRelation(e){o=e}};return s}const r=createTailorDBField;function uuid(e){return r(`uuid`,e)}function string(e){return r(`string`,e)}function bool(e){return r(`boolean`,e)}function int(e){return r(`integer`,e)}function float(e){return r(`float`,e)}function decimal(e){if(e?.scale!==void 0&&(!Number.isInteger(e.scale)||e.scale<0||e.scale>12))throw Error(`scale must be an integer between 0 and 12`);let t=r(`decimal`,e);return e?.scale!==void 0&&(t._metadata.scale=e.scale),t}function date(e){return r(`date`,e)}function datetime(e){return r(`datetime`,e)}function time(e){return r(`time`,e)}function _enum(e,t){return r(`enum`,t,void 0,e)}function object(e,t){return r(`nested`,t,e)}function createTailorDBType(t,n,r){let i=r.description,a={},o=[],s={},c={},l=[],u,d,f=new Set;r.description!==void 0&&f.add(`description`);function runMethodOnce(e,t){if(f.has(e))throw Error(`.${e}() has already been set`);let n=t();return f.add(e),n}if(r.pluralForm){if(t===r.pluralForm)throw Error(`The name and the plural form must be different. name=${t}`);a.pluralForm=r.pluralForm}let p={name:t,fields:{...n},_output:null,_description:i,get metadata(){let e={};return o.length>0&&o.forEach(t=>{let n=t.fields.map(e=>String(e)),r=t.name||`idx_${n.join(`_`)}`;e[r]={fields:n,unique:t.unique}}),{name:this.name,description:i,settings:a,permissions:s,files:c,...Object.keys(e).length>0&&{indexes:e},...u&&{typeHook:u},...d&&{typeValidate:d}}},hooks(e){return runMethodOnce(`hooks`,()=>(u=e,this))},validate(e){return runMethodOnce(`validate`,()=>(d=e,this))},features(e){return runMethodOnce(`features`,()=>(a={...a,...e},this))},indexes(...e){return runMethodOnce(`indexes`,()=>(o=e,this))},files(e){return runMethodOnce(`files`,()=>(c=e,this))},permission(e){return runMethodOnce(`permission`,()=>{let t=this;return s.record=e,t})},gqlPermission(e){return runMethodOnce(`gqlPermission`,()=>{let t=this;return s.gql=e,t})},description(e){return runMethodOnce(`description`,()=>(i=e,this._description=e,this))},pickFields(e,t){let n={};for(let r of e){let e=this.fields[r];n[r]=t?e.clone(t):e}return n},omitFields(e){let t=new Set(e),n={};for(let e in this.fields)Object.hasOwn(this.fields,e)&&!t.has(e)&&(n[e]=this.fields[e]);return n},get plugins(){return l},plugin(e){for(let[t,n]of Object.entries(e))l.push({pluginId:t,config:n});return this}};return e(p,`tailordb-type`)}const i=uuid();function dbTable(e,t,n){let r=Array.isArray(e)?e[0]:e,a=Array.isArray(e)?e[1]:void 0,o,s;return typeof t==`string`?(o=t,s=n):s=t,createTailorDBType(r,{id:i,...s},{pluralForm:a,description:o})}const timestampsUpdatedAtHook=({input:e,now:t})=>e??t,a=Symbol.for(`tailor-platform/sdk:precompiled-script-expr`);timestampsUpdatedAtHook[a]={"hooks.update":`(({ input, now }) => input ?? now)({ input: _value, oldValue: _oldValue, invoker: _principal, now: _now })`};const o={table:dbTable,uuid,string,bool,int,float,decimal,date,datetime,time,enum:_enum,object,fields:{timestamps:()=>({createdAt:datetime().default(`now`).description(`Record creation timestamp`),updatedAt:datetime().default(`now`).hooks({update:timestampsUpdatedAtHook}).description(`Record update timestamp`)})}};export{parseInternal as i,mapAllowedValues as n,parseInputFields as r,o as t};
|
|
2
|
-
//# sourceMappingURL=schema-
|
|
1
|
+
import{t as e}from"./brand-C8nMKhJC.mjs";import{cloneDeep as t}from"es-toolkit";const n={uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/,time:/^(?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d)$/,datetime:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d):(?<second>[0-5]\d|60)(\.(?<fraction>\d+))?(?<offset>[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/,decimal:/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/};function validateBaseValue(e){let{field:t,value:r,pathArray:i,issues:a}=e,o=i.length>0?i:void 0,s=a.length;switch(t.type){case`string`:typeof r!=`string`&&a.push({message:`Expected a string: received ${String(r)}`,path:o});break;case`integer`:(typeof r!=`number`||!Number.isInteger(r))&&a.push({message:`Expected an integer: received ${String(r)}`,path:o});break;case`float`:(typeof r!=`number`||!Number.isFinite(r))&&a.push({message:`Expected a number: received ${String(r)}`,path:o});break;case`boolean`:typeof r!=`boolean`&&a.push({message:`Expected a boolean: received ${String(r)}`,path:o});break;case`uuid`:(typeof r!=`string`||!n.uuid.test(r))&&a.push({message:`Expected a valid UUID: received ${String(r)}`,path:o});break;case`date`:(typeof r!=`string`||!n.date.test(r))&&a.push({message:`Expected to match "yyyy-MM-dd" format: received ${String(r)}`,path:o});break;case`datetime`:(typeof r!=`string`||!n.datetime.test(r))&&a.push({message:`Expected to match ISO format: received ${String(r)}`,path:o});break;case`time`:(typeof r!=`string`||!n.time.test(r))&&a.push({message:`Expected to match "HH:mm" format: received ${String(r)}`,path:o});break;case`decimal`:(typeof r!=`string`||!n.decimal.test(r))&&a.push({message:`Expected a decimal string: received ${String(r)}`,path:o});break;case`enum`:if(t._metadata.allowedValues){let e=t._metadata.allowedValues.map(e=>e.value);(typeof r!=`string`||!e.includes(r))&&a.push({message:`Must be one of [${e.join(`, `)}]: received ${String(r)}`,path:o})}break;case`nested`:{if(typeof r!=`object`||!r||Array.isArray(r)||r instanceof Date)return a.push({message:`Expected an object: received ${String(r)}`,path:o}),!1;let n=!0;for(let[a,o]of Object.entries(t.fields)){let t=r[a];validateBaseField({...e,field:o,value:t,pathArray:i.concat(a)})||(n=!1)}return n}}return a.length===s}function validateCustomValue(e,t){let{value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0;for(let e of t){let t=e({value:n});typeof t==`string`&&i.push({message:t,path:a})}}function validateBaseField(e){let{field:t,value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0,o=n==null;if(t._metadata.required&&o)return i.push({message:`Required field is missing`,path:a}),!1;if(!t._metadata.required&&o)return!0;let s=!0;if(t._metadata.array){if(!Array.isArray(n))return i.push({message:`Expected an array`,path:a}),!1;for(let t=0;t<n.length;t++)validateBaseValue({...e,value:n[t],pathArray:r.concat(`[${t}]`)})||(s=!1)}else s=validateBaseValue(e);return s}function validateCustomField(e){let{field:t,value:n,pathArray:r}=e;if(n==null)return;if(t.type===`nested`){let i=t._metadata.array?n:[n];for(let n=0;n<i.length;n++){let a=i[n],o=t._metadata.array?r.concat(`[${n}]`):r;for(let[n,r]of Object.entries(t.fields))validateCustomField({...e,field:r,value:a[n],pathArray:o.concat(n)})}}let i=t._metadata.validate;i?.length&&validateCustomValue(e,i)}function parseInternal(e){let{value:t}=e,n=[],r={...e,issues:n};return validateBaseField(r)&&validateCustomField(r),n.length>0?{issues:n}:{value:t??null}}function parseInputFields(e){let{fields:t,...n}=e;return parseInternal({...n,field:{type:`nested`,fields:t,_metadata:{required:!0}},pathArray:[]})}function mapAllowedValues(e){return e.map(e=>typeof e==`string`?{value:e,description:``}:{...e,description:e.description??``})}function createTailorDBField(e,t,n,r){return createTailorDBFieldRuntime(e,t,n,r)}function createTailorDBFieldRuntime(e,n,r,i){let a={required:!0},o;n&&(n.optional===!0&&(a.required=!1),n.array===!0&&(a.array=!0)),i&&(a.allowedValues=mapAllowedValues(i));function parseInternal$1(e){return parseInternal({...e,field:s})}function cloneWith(e){let t=s.clone();return Object.assign(t._metadata,e),t}let s={type:e,fields:r??{},_defined:void 0,_output:void 0,_metadata:a,get metadata(){return{...this._metadata}},get rawRelation(){return o?{...o,toward:{...o.toward}}:void 0},description(e){return cloneWith({description:e})},typeName(e){return cloneWith({typeName:e})},validate(...e){return cloneWith({validate:e})},parse(e){return parseInternal$1({value:e.value,data:e.data,invoker:e.invoker,pathArray:[]})},relation(e){let t=s.clone(),n=e.toward,r=`table`in n?n.table:n.type,i=r===`self`?`self`:r.name;return t._setRawRelation({type:e.type,toward:{table:i,as:e.toward.as,key:e.toward.key},backward:e.backward}),t},index(){return cloneWith({index:!0})},unique(){return cloneWith({unique:!0,index:!0})},vector(){return cloneWith({vector:!0})},default(e){return cloneWith({default:e})},hooks(e){return cloneWith({hooks:e})},serial(e){return cloneWith({serial:e})},clone(a){if(this._metadata.validate?.length&&a?.array!==void 0&&a.array!==(this._metadata.array===!0))throw Error(`Cannot change the array option on a field with custom validation`);let s=r;if(r){let e={};for(let[t,n]of Object.entries(r))e[t]=n.clone();s=e}let c=createTailorDBFieldRuntime(e,n,s,i);return Object.assign(c._metadata,t(this._metadata)),a&&(a.optional!==void 0&&(c._metadata.required=!a.optional),a.array!==void 0&&(c._metadata.array=a.array)),o&&c._setRawRelation(t(o)),c},_setRawRelation(e){o=e}};return s}const r=createTailorDBField;function uuid(e){return r(`uuid`,e)}function string(e){return r(`string`,e)}function bool(e){return r(`boolean`,e)}function int(e){return r(`integer`,e)}function float(e){return r(`float`,e)}function decimal(e){if(e?.scale!==void 0&&(!Number.isInteger(e.scale)||e.scale<0||e.scale>12))throw Error(`scale must be an integer between 0 and 12`);let t=r(`decimal`,e);return e?.scale!==void 0&&(t._metadata.scale=e.scale),t}function date(e){return r(`date`,e)}function datetime(e){return r(`datetime`,e)}function time(e){return r(`time`,e)}function _enum(e,t){return r(`enum`,t,void 0,e)}function object(e,t){return r(`nested`,t,e)}function createTailorDBType(t,n,r){let i=r.description,a={},o=[],s={},c={},l=[],u,d,f=new Set;r.description!==void 0&&f.add(`description`);function runMethodOnce(e,t){if(f.has(e))throw Error(`.${e}() has already been set`);let n=t();return f.add(e),n}if(r.pluralForm){if(t===r.pluralForm)throw Error(`The name and the plural form must be different. name=${t}`);a.pluralForm=r.pluralForm}let p={name:t,fields:{...n},_output:null,_description:i,get metadata(){let e={};return o.length>0&&o.forEach(t=>{let n=t.fields.map(e=>String(e)),r=t.name||`idx_${n.join(`_`)}`;e[r]={fields:n,unique:t.unique}}),{name:this.name,description:i,settings:a,permissions:s,files:c,...Object.keys(e).length>0&&{indexes:e},...u&&{typeHook:u},...d&&{typeValidate:d}}},hooks(e){return runMethodOnce(`hooks`,()=>(u=e,this))},validate(e){return runMethodOnce(`validate`,()=>(d=e,this))},features(e){return runMethodOnce(`features`,()=>(a={...a,...e},this))},indexes(...e){return runMethodOnce(`indexes`,()=>(o=e,this))},files(e){return runMethodOnce(`files`,()=>(c=e,this))},permission(e){return runMethodOnce(`permission`,()=>{let t=this;return s.record=e,t})},gqlPermission(e){return runMethodOnce(`gqlPermission`,()=>{let t=this;return s.gql=e,t})},description(e){return runMethodOnce(`description`,()=>(i=e,this._description=e,this))},pickFields(e,t){let n={};for(let r of e){let e=this.fields[r];if(!e)throw Error(`pickFields(): field "${String(r)}" does not exist on this table yet. If it comes from a plugin's .plugin() call, it is only added to the table after \`tailor generate\` runs.`);n[r]=t?e.clone(t):e}return n},omitFields(e){let t=new Set(e),n={};for(let e in this.fields)Object.hasOwn(this.fields,e)&&!t.has(e)&&(n[e]=this.fields[e]);return n},get plugins(){return l},plugin(e){for(let[t,n]of Object.entries(e))l.push({pluginId:t,config:n});return this}};return e(p,`tailordb-type`)}const i=uuid();function dbTable(e,t,n){let r=Array.isArray(e)?e[0]:e,a=Array.isArray(e)?e[1]:void 0,o,s;return typeof t==`string`?(o=t,s=n):s=t,createTailorDBType(r,{id:i,...s},{pluralForm:a,description:o})}const timestampsUpdatedAtHook=({input:e,now:t})=>e??t,a=Symbol.for(`tailor-platform/sdk:precompiled-script-expr`);timestampsUpdatedAtHook[a]={"hooks.update":`(({ input, now }) => input ?? now)({ input: _value, oldValue: _oldValue, invoker: _principal, now: _now })`};const o={table:dbTable,uuid,string,bool,int,float,decimal,date,datetime,time,enum:_enum,object,fields:{timestamps:()=>({createdAt:datetime().default(`now`).description(`Record creation timestamp`),updatedAt:datetime().default(`now`).hooks({update:timestampsUpdatedAtHook}).description(`Record update timestamp`)})}};export{parseInternal as i,mapAllowedValues as n,parseInputFields as r,o as t};
|
|
2
|
+
//# sourceMappingURL=schema-6d_OHyZf.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-6d_OHyZf.mjs","names":["parseInternal","parseFieldInternal"],"sources":["../src/runtime/field-parse.ts","../src/configure/types/field.ts","../src/configure/services/tailordb/schema.ts"],"sourcesContent":["import type { FieldMetadata, TailorFieldType } from \"#/configure/types/field.types\";\nimport type { TailorPrincipal } from \"#/runtime/types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d)$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})[Tt](?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d):(?<second>[0-5]\\d|60)(\\.(?<fraction>\\d+))?(?<offset>[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\nexport type FieldParseArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n};\n\nexport type FieldParseInternalArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n pathArray: string[];\n};\n\nexport type FieldRuntime<T extends TailorFieldType = TailorFieldType> = {\n readonly type: T;\n readonly fields: Record<string, FieldRuntime>;\n _metadata: FieldMetadata;\n};\n\ntype FieldParseRuntimeArgs<T extends TailorFieldType> = FieldParseInternalArgs & {\n field: FieldRuntime<T>;\n};\n\ntype FieldValidationArgs<T extends TailorFieldType> = FieldParseRuntimeArgs<T> & {\n issues: StandardSchemaV1.Issue[];\n};\n\nfunction validateBaseValue<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n const initialIssueCount = issues.length;\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path,\n });\n }\n }\n break;\n\n case \"nested\": {\n // Runtime input may not match the declared field type.\n // oxlint-disable typescript/no-unnecessary-condition\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n // oxlint-enable typescript/no-unnecessary-condition\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path,\n });\n return false;\n }\n\n let nestedBaseValid = true;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = (value as Record<string, unknown>)[fieldName];\n if (\n !validateBaseField({\n ...args,\n field: nestedField,\n value: fieldValue,\n pathArray: pathArray.concat(fieldName),\n })\n ) {\n nestedBaseValid = false;\n }\n }\n return nestedBaseValid;\n }\n }\n\n return issues.length === initialIssueCount;\n}\n\nfunction validateCustomValue<T extends TailorFieldType>(\n args: FieldValidationArgs<T>,\n validateFns: NonNullable<FieldMetadata[\"validate\"]>,\n): void {\n const { value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n for (const fn of validateFns) {\n const result = fn({ value });\n if (typeof result === \"string\") {\n issues.push({\n message: result,\n path,\n });\n }\n }\n}\n\nfunction validateBaseField<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path,\n });\n return false;\n }\n\n if (!field._metadata.required && isNullOrUndefined) {\n return true;\n }\n\n let baseValid = true;\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path,\n });\n return false;\n }\n\n for (let i = 0; i < value.length; i++) {\n if (\n !validateBaseValue({\n ...args,\n value: value[i],\n pathArray: pathArray.concat(`[${i}]`),\n })\n ) {\n baseValid = false;\n }\n }\n } else {\n baseValid = validateBaseValue(args);\n }\n\n return baseValid;\n}\n\nfunction validateCustomField<T extends TailorFieldType>(args: FieldValidationArgs<T>): void {\n const { field, value, pathArray } = args;\n if (value === null || value === undefined) {\n return;\n }\n\n if (field.type === \"nested\") {\n const records = field._metadata.array\n ? (value as Record<string, unknown>[])\n : [value as Record<string, unknown>];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i] as Record<string, unknown>;\n const recordPath = field._metadata.array ? pathArray.concat(`[${i}]`) : pathArray;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n validateCustomField({\n ...args,\n field: nestedField,\n value: record[fieldName],\n pathArray: recordPath.concat(fieldName),\n });\n }\n }\n }\n\n const validateFns = field._metadata.validate;\n if (validateFns?.length) {\n validateCustomValue(args, validateFns);\n }\n}\n\nexport function parseInternal<T extends TailorFieldType, Output>(\n args: FieldParseRuntimeArgs<T>,\n): StandardSchemaV1.Result<Output> {\n const { value } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n const validationArgs = { ...args, issues };\n const baseValid = validateBaseField(validationArgs);\n if (baseValid) {\n validateCustomField(validationArgs);\n }\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value: (value ?? null) as Output };\n}\n\ntype ParseInputFieldsArgs = FieldParseArgs & {\n fields: Record<string, FieldRuntime>;\n};\n\n/**\n * Validate a value against a record of input fields, treating the record as a\n * single required object — the same code path deployed functions run via\n * `t.object(fields).parse(...)`, so local validation matches platform behavior.\n * @param args - Input field definitions plus the value, context data, and user\n * @returns Validation result\n */\nexport function parseInputFields(args: ParseInputFieldsArgs): StandardSchemaV1.Result<unknown> {\n const { fields, ...parseArgs } = args;\n return parseInternal({\n ...parseArgs,\n field: { type: \"nested\", fields, _metadata: { required: true } },\n pathArray: [],\n });\n}\n","import type { EnumValue } from \"#/configure/types/field.types\";\n\nexport type AllowedValues = readonly [string | EnumValue, ...(string | EnumValue)[]];\n\n/**\n * Normalize allowed values into EnumValue objects with descriptions.\n * @param values - Allowed values as strings or EnumValue objects\n * @returns Normalized allowed values\n */\nexport function mapAllowedValues(values: AllowedValues): EnumValue[] {\n return values.map((value) => {\n if (typeof value === \"string\") {\n return { value, description: \"\" };\n }\n return { ...value, description: value.description ?? \"\" };\n });\n}\n\nexport type AllowedValuesOutput<V extends AllowedValues> = V[number] extends infer T\n ? T extends string\n ? T\n : T extends { value: infer K }\n ? K\n : never\n : never;\n","import { cloneDeep } from \"es-toolkit\";\nimport {\n type AllowedValues,\n type AllowedValuesOutput,\n mapAllowedValues,\n} from \"#/configure/types/field\";\nimport {\n parseInternal as parseFieldInternal,\n type FieldParseArgs,\n type FieldParseInternalArgs,\n} from \"#/runtime/field-parse\";\nimport { brandValue } from \"#/utils/brand\";\nimport type {\n FieldOptions,\n FieldOutput,\n TailorFieldType,\n TailorToTs,\n FieldValidateInput,\n} from \"#/configure/types/field.types\";\nimport type {\n PrecompiledScriptExprKey,\n PrecompiledScriptExprMap,\n} from \"#/parser/service/tailordb/types\";\nimport type { PluginAttachment, PluginConfigs, PluginFieldExtensions } from \"#/plugin/types\";\nimport type { InferredAttributes } from \"#/runtime/types\";\nimport type {\n output,\n InferFieldsOutput,\n IsUnion,\n TypeLevelError,\n UnionToIntersection,\n} from \"#/types/helpers\";\nimport type { RawPermissions } from \"#/types/tailordb.generated\";\nimport type { TailorTypeGqlPermission, TailorTypePermission } from \"./permission\";\nimport type {\n TailorDBField as TailorDBFieldBase,\n TailorDBType as TailorDBTypeBase,\n DBFieldMetadata,\n DefinedDBFieldMetadata,\n SerialConfig,\n IndexDef,\n TailorDBTypeMetadata,\n RawRelationConfig,\n RelationType,\n Hook,\n TypeHook,\n UpdateHookFn,\n ExcludeNestedDBFields,\n ExcludeHookedDBFields,\n ExcludeDefaultedDBFields,\n TypeFeatures,\n TypeValidateFn,\n} from \"./types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n// Erased DB fields stay assignable across builder method-state changes.\n// oxlint-disable-next-line no-explicit-any\ntype AnyBuilderMethod = any;\n\nexport type TailorAnyDBField = Omit<\n TailorDBFieldBase<AnyBuilderMethod, AnyBuilderMethod>,\n \"fields\"\n> & {\n readonly fields: Record<string, AnyBuilderMethod>;\n _metadata: DBFieldMetadata;\n parse: AnyBuilderMethod;\n readonly typeName: TypeLevelError<string>;\n description: AnyBuilderMethod;\n relation: AnyBuilderMethod;\n index: AnyBuilderMethod;\n unique: AnyBuilderMethod;\n vector: AnyBuilderMethod;\n default: AnyBuilderMethod;\n hooks: AnyBuilderMethod;\n validate: AnyBuilderMethod;\n serial: AnyBuilderMethod;\n clone: AnyBuilderMethod;\n};\n\n// Helper alias\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyDBType = TailorDBType<any, any, any>;\n\ntype IsAny<T> = 0 extends 1 & T ? true : false;\ntype DBFieldTypeNameMethod<Defined extends DefinedDBFieldMetadata> =\n IsAny<Defined> extends true\n ? TypeLevelError<string>\n : TypeLevelError<\"typeName cannot be used on TailorDB fields\">;\n\ntype WithDBFieldDescription<Defined> = Defined & { description: true };\ntype WithDBFieldRelation<Defined, S extends RelationType | RelationSelfConfig> = S extends\n | \"oneToOne\"\n | \"1-1\"\n ? Defined & { unique: true; index: true; relation: true }\n : S extends { type: \"oneToOne\" | \"1-1\" }\n ? Defined & { unique: true; index: true; relation: true }\n : Defined & { index: true; relation: true };\ntype WithDBFieldIndex<Defined> = Defined & { index: true };\ntype WithDBFieldUnique<Defined> = Defined & { unique: true; index: true };\ntype WithDBFieldVector<Defined> = Defined & { vector: true };\ntype WithDBFieldHooks<Defined, H> = Defined & {\n hooks: {\n create: H extends { create: unknown } ? true : false;\n update: H extends { update: unknown } ? true : false;\n };\n serial: false;\n};\ntype WithDBFieldDefault<Defined> = Defined & { default: true };\ntype WithDBFieldValidate<Defined> = Defined & { validate: true };\ntype WithDBFieldSerial<Defined> = Defined & {\n serial: true;\n hooks: { create: false; update: false };\n};\ntype WithDBFieldCloneOptions<Defined extends DefinedDBFieldMetadata, NewOpt extends FieldOptions> =\n IsAny<Defined> extends true\n ? Defined\n : Omit<Defined, \"array\"> & {\n array: NewOpt extends { array: true }\n ? true\n : NewOpt extends { array: false }\n ? false\n : Defined[\"array\"];\n };\ntype NonNullableDBFieldOutput<Output> = Exclude<Output, null>;\ntype DBFieldScalarOutput<Output> =\n NonNullableDBFieldOutput<Output> extends (infer Item)[] ? Item : NonNullableDBFieldOutput<Output>;\ntype DBFieldCloneArrayOutput<Output, NewOpt extends FieldOptions> = NewOpt extends {\n array: true;\n}\n ? DBFieldScalarOutput<Output>[]\n : NewOpt extends { array: false }\n ? DBFieldScalarOutput<Output>\n : NonNullableDBFieldOutput<Output>;\ntype DBFieldCloneOutput<Output, NewOpt extends FieldOptions> = NewOpt extends { optional: true }\n ? DBFieldCloneArrayOutput<Output, NewOpt> | null\n : NewOpt extends { optional: false }\n ? DBFieldCloneArrayOutput<Output, NewOpt>\n : null extends Output\n ? DBFieldCloneArrayOutput<Output, NewOpt> | null\n : DBFieldCloneArrayOutput<Output, NewOpt>;\ntype DBFieldCloneOptions<Defined extends DefinedDBFieldMetadata> = Omit<FieldOptions, \"array\"> & {\n array?: Defined extends { validate: unknown } ? Defined[\"array\"] : boolean;\n};\ntype InvalidValidatedArrayCloneKeys<\n Fields extends Record<string, TailorAnyDBField>,\n K extends keyof Fields,\n Opt extends FieldOptions,\n> = Opt extends { array: infer ArrayOption }\n ? {\n [P in K]: Fields[P] extends TailorDBField<infer Defined, infer _Output>\n ? Defined extends { validate: unknown }\n ? ArrayOption extends Defined[\"array\"]\n ? never\n : P\n : never\n : never;\n }[K]\n : never;\ntype DBFieldsCloneOptionsGuard<\n Fields extends Record<string, TailorAnyDBField>,\n K extends keyof Fields,\n Opt extends FieldOptions,\n> = [InvalidValidatedArrayCloneKeys<Fields, K, Opt>] extends [never]\n ? unknown\n : TypeLevelError<\"array cannot be changed on fields with custom validation\">;\ntype DefinedDBTypeMetadata = {\n hooks?: true;\n validate?: true;\n features?: true;\n indexes?: true;\n files?: true;\n permission?: true;\n gqlPermission?: true;\n description?: true;\n};\ntype WithDBTypeMetadata<\n Defined extends DefinedDBTypeMetadata,\n Key extends keyof DefinedDBTypeMetadata,\n> = Defined & Record<Key, true>;\ntype DBTypeDuplicateInputGuard<\n Defined extends DefinedDBTypeMetadata,\n Key extends keyof DefinedDBTypeMetadata,\n Input,\n Message extends string,\n> =\n IsAny<Defined> extends true\n ? Input\n : Defined extends Record<Key, unknown>\n ? TypeLevelError<Message>\n : Input;\ntype DBTypeDuplicateRestGuard<\n Defined extends DefinedDBTypeMetadata,\n Key extends keyof DefinedDBTypeMetadata,\n Input extends unknown[],\n Message extends string,\n> =\n IsAny<Defined> extends true\n ? Input\n : Defined extends Record<Key, unknown>\n ? [TypeLevelError<Message>, ...TypeLevelError<Message>[]]\n : Input;\ntype FileKeyConflictError<\n Fields extends Record<string, TailorAnyDBField>,\n User extends object,\n> = Partial<\n Record<\n keyof output<TailorDBType<Fields, User>> & string,\n TypeLevelError<\"file keys cannot use existing field names\">\n >\n>;\n// A plugin id with no PluginFieldExtensions entry contributes no keys — using\n// Record<never, never> (rather than Record<string, never>) keeps its `keyof`\n// empty so it can't spuriously collide with every existing field.\ntype PluginFieldExtensionFor<\n Fields extends Record<string, TailorAnyDBField>,\n Id extends string,\n IdConfig,\n> = Id extends keyof PluginFieldExtensions<keyof Fields & string, IdConfig>\n ? PluginFieldExtensions<keyof Fields & string, IdConfig>[Id]\n : Record<never, never>;\ntype PluginFieldExtensionsUnion<\n Fields extends Record<string, TailorAnyDBField>,\n Config extends Record<string, unknown>,\n> = {\n [Id in keyof Config & string]: PluginFieldExtensionFor<Fields, Id, Config[Id]>;\n}[keyof Config & string];\ntype AllExtensionKeys<Ext> = Ext extends unknown ? keyof Ext : never;\n// True when plugin `Id` has a PluginFieldExtensions entry whose type does not\n// extend Record<string, TailorAnyDBField> — e.g. a plugin author registered\n// a non-record shape by mistake. Checked ahead of PluginFieldConflict, since\n// `keyof` on a non-record shape (e.g. `keyof string`) would otherwise produce\n// nonsense candidate keys for the collision check.\n// `Id extends string` (not `keyof Config & string`) deliberately: a mapped\n// type's key variable, used inside a nested conditional branch and then\n// intersected with `string`, does not structurally satisfy a `keyof Config &\n// string`-constrained type parameter under `skipLibCheck: false` (verified\n// against a standalone consumer — TS2344 on both call sites otherwise, even\n// for code that never calls .plugin()). `Config[Id & keyof Config]` recovers\n// the same indexed-access result without that constraint.\ntype PluginFieldExtensionShapeError<\n Fields extends Record<string, TailorAnyDBField>,\n Config extends Record<string, unknown>,\n Id extends string,\n> =\n PluginFieldExtensionFor<Fields, Id, Config[Id & keyof Config]> extends Record<\n string,\n TailorAnyDBField\n >\n ? false\n : true;\n// True when the fields plugin `Id` would inject collide with an existing\n// field, or with a field injected by another plugin id attached in the same\n// .plugin() call.\ntype PluginFieldConflict<\n Fields extends Record<string, TailorAnyDBField>,\n Config extends Record<string, unknown>,\n Id extends string,\n FileKeys extends string,\n> = [\n AllExtensionKeys<PluginFieldExtensionFor<Fields, Id, Config[Id & keyof Config]>> &\n (\n | keyof Fields\n | FileKeys\n | AllExtensionKeys<PluginFieldExtensionsUnion<Fields, Omit<Config, Id>>>\n ),\n] extends [never]\n ? false\n : true;\n// Rejects a property on the caller's config literal for plugin `Id` that\n// isn't part of its registered PluginConfigs shape. `Config` is captured by\n// a `const` type parameter from the argument itself, so intersecting the\n// success branch with `PluginConfigs<...>[Id]` alone would not trigger\n// TypeScript's excess-property check — that check only fires when an object\n// literal is validated directly against a target type, not after its shape\n// has already been inferred through a generic parameter.\ntype PluginConfigExcessProps<\n Fields extends Record<string, TailorAnyDBField>,\n Config extends Record<string, unknown>,\n Id extends string,\n> = Record<\n Exclude<\n keyof Config[Id & keyof Config],\n keyof PluginConfigs<keyof Fields & string>[Id & keyof PluginConfigs<keyof Fields & string>]\n >,\n never\n>;\ntype PluginExtendedFields<\n Fields extends Record<string, TailorAnyDBField>,\n Config extends Record<string, unknown>,\n> =\n IsAny<Fields> extends true\n ? Fields\n : // For `Config = {}`, PluginFieldExtensionsUnion is `never`, and\n // UnionToIntersection<never> is `unknown` (not `never`), so this\n // correctly reduces to `Fields` — see the \"empty config\" test.\n Fields & UnionToIntersection<PluginFieldExtensionsUnion<Fields, Config>>;\n// Validates each key of the passed config object against PluginConfigs and\n// flags field-extension conflicts (see PluginFieldConflict above), keeping\n// type errors localized to the offending plugin id instead of requiring\n// every registered plugin id to be present (as a `P extends keyof\n// PluginConfigs<...>` generic would need, defeating inference of which\n// plugin ids were actually passed).\ntype PluginConfigGuard<\n Fields extends Record<string, TailorAnyDBField>,\n Config extends Record<string, unknown>,\n FileKeys extends string,\n> =\n IsAny<Fields> extends true\n ? unknown\n : {\n [K in keyof Config]: K extends keyof PluginConfigs<keyof Fields & string>\n ? // A union config (e.g. from a ternary passed directly as a plugin's\n // value) distributes through PluginFieldExtensionFor's conditional\n // and silently collapses the injected field to `never` once\n // intersected back together — reject it here instead, before it\n // can produce that confusing downstream error.\n IsUnion<Config[K]> extends true\n ? TypeLevelError<\"plugin config must be a single object literal, not a union — assign the config to a variable first if it comes from a conditional expression\">\n : PluginFieldExtensionShapeError<Fields, Config, K & string> extends true\n ? TypeLevelError<\"PluginFieldExtensions entry must be a Record<string, TailorAnyDBField>\">\n : PluginFieldConflict<Fields, Config, K & string, FileKeys> extends true\n ? TypeLevelError<\"plugin field extension conflicts with an existing field, a file key declared via .files(), or another plugin's field\">\n : PluginConfigs<keyof Fields & string>[K] &\n PluginConfigExcessProps<Fields, Config, K & string>\n : TypeLevelError<\"unknown plugin id\">;\n };\ntype DBFieldDescriptionFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (description: string) => TailorDBField<WithDBFieldDescription<Defined>, Output, Nested>;\ntype DBFieldRelationFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = {\n <S extends RelationType, T extends TailorAnyDBType>(\n config: RelationConfig<S, T>,\n ): TailorDBField<WithDBFieldRelation<Defined, S>, Output, Nested>;\n <S extends RelationSelfConfig>(\n config: S,\n ): TailorDBField<WithDBFieldRelation<Defined, S>, Output, Nested>;\n};\ntype DBFieldIndexFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = () => TailorDBField<WithDBFieldIndex<Defined>, Output, Nested>;\ntype DBFieldUniqueFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = () => TailorDBField<WithDBFieldUnique<Defined>, Output, Nested>;\ntype DBFieldVectorFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = () => TailorDBField<WithDBFieldVector<Defined>, Output, Nested>;\ntype DBFieldHooksFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = <\n const H extends Hook<\n Output,\n Defined extends { default: true } ? Output | null | undefined : Output\n >,\n>(\n hooks: H,\n) => TailorDBField<WithDBFieldHooks<Defined, H>, Output, Nested>;\ntype DBFieldValidateFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (\n ...validate: FieldValidateInput<Output>[]\n) => TailorDBField<WithDBFieldValidate<Defined>, Output, Nested>;\ntype DBFieldSerialFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (\n config: SerialConfig<Defined[\"type\"] & (\"integer\" | \"string\")>,\n) => TailorDBField<WithDBFieldSerial<Defined>, Output, Nested>;\ntype DBFieldDescriptionMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldDescriptionFn<Defined, Output, Nested>\n : Defined extends { description: unknown }\n ? TypeLevelError<\".description() has already been set\">\n : DBFieldDescriptionFn<Defined, Output, Nested>;\ntype DBFieldRelationMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldRelationFn<Defined, Output, Nested>\n : Defined extends { relation: unknown }\n ? TypeLevelError<\".relation() has already been set\">\n : DBFieldRelationFn<Defined, Output, Nested>;\ntype DBFieldArrayCheck<A extends boolean, Ok, Msg extends string> = A extends true\n ? TypeLevelError<Msg>\n : Ok;\ntype DBFieldIndexMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldIndexFn<Defined, Output, Nested>\n : Defined extends { index: unknown }\n ? TypeLevelError<\".index() has already been set\">\n : DBFieldArrayCheck<\n Defined[\"array\"],\n DBFieldIndexFn<Defined, Output, Nested>,\n \"index cannot be set on array fields\"\n >;\ntype DBFieldUniqueMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldUniqueFn<Defined, Output, Nested>\n : Defined extends { unique: unknown }\n ? TypeLevelError<\".unique() has already been set\">\n : DBFieldArrayCheck<\n Defined[\"array\"],\n DBFieldUniqueFn<Defined, Output, Nested>,\n \"unique cannot be set on array fields\"\n >;\ntype DBFieldVectorMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldVectorFn<Defined, Output, Nested>\n : Defined extends { vector: unknown }\n ? TypeLevelError<\".vector() has already been set\">\n : Defined extends { type: \"string\"; array: false }\n ? DBFieldVectorFn<Defined, Output, Nested>\n : TypeLevelError<\"vector can only be set on non-array string fields\">;\ntype DBFieldHooksMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldHooksFn<Defined, Output, Nested>\n : Defined extends {\n serial: true;\n hooks: { create: false; update: false };\n }\n ? TypeLevelError<\"hooks cannot be set after serial\">\n : Defined extends {\n hooks: unknown;\n }\n ? TypeLevelError<\".hooks() has already been set\">\n : Defined extends { type: \"nested\" }\n ? TypeLevelError<\"hooks cannot be set on nested type fields\">\n : DBFieldHooksFn<Defined, Output, Nested>;\ntype DBFieldValidateMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldValidateFn<Defined, Output, Nested>\n : Defined extends { validate: unknown }\n ? TypeLevelError<\".validate() has already been set\">\n : DBFieldValidateFn<Defined, Output, Nested>;\ntype DBFieldSerialMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldSerialFn<Defined, Output, Nested>\n : Defined extends { serial: true }\n ? TypeLevelError<\".serial() has already been set\">\n : Defined extends { serial: false }\n ? TypeLevelError<\"serial cannot be set after hooks\">\n : IsAny<Output> extends true\n ? Defined extends { type: \"integer\" | \"string\"; array: false }\n ? DBFieldSerialFn<Defined, Output, Nested>\n : TypeLevelError<\"serial can only be set on non-array integer or string fields\">\n : null extends Output\n ? TypeLevelError<\"serial can only be set on non-array integer or string fields\">\n : Defined extends { type: \"integer\" | \"string\"; array: false }\n ? DBFieldSerialFn<Defined, Output, Nested>\n : TypeLevelError<\"serial can only be set on non-array integer or string fields\">;\ntype DBFieldDefaultFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (\n value: Output extends null ? NonNullable<Output> : Output,\n) => TailorDBField<WithDBFieldDefault<Defined>, Output, Nested>;\ntype DBFieldDefaultMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldDefaultFn<Defined, Output, Nested>\n : Defined extends { default: unknown }\n ? TypeLevelError<\".default() has already been set\">\n : Defined extends { type: \"nested\" }\n ? TypeLevelError<\"default cannot be set on nested type fields\">\n : Defined extends { serial: true }\n ? TypeLevelError<\"default cannot be set on serial fields\">\n : null extends Output\n ? TypeLevelError<\"default cannot be set on optional fields\">\n : DBFieldDefaultFn<Defined, Output, Nested>;\n\n/**\n * Full TailorDBField interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorDBField<\n Defined extends DefinedDBFieldMetadata = DefinedDBFieldMetadata,\n // oxlint-disable-next-line no-explicit-any\n Output = any,\n // Nested object fields, so a `db.object()` field keeps the shape it was declared with.\n // Every builder method passes it through; dropping it here would erase the shape as\n // soon as one is chained.\n Nested extends Record<string, TailorAnyDBField> = Record<string, TailorAnyDBField>,\n> extends Omit<TailorDBFieldBase<Defined, Output, Nested>, \"fields\"> {\n readonly fields: Nested;\n _metadata: DBFieldMetadata;\n\n /**\n * Parse and validate a value against this field's validation rules\n */\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n\n /**\n * typeName is not available on TailorDB fields.\n * Use typeName on pipeline fields (t.enum / t.object) instead.\n */\n typeName: DBFieldTypeNameMethod<Defined>;\n\n /**\n * Set a description for the field\n */\n description: DBFieldDescriptionMethod<Defined, Output, Nested>;\n\n /**\n * Define a relation to another table.\n */\n relation: DBFieldRelationMethod<Defined, Output, Nested>;\n\n /**\n * Add an index to the field\n */\n index: DBFieldIndexMethod<Defined, Output, Nested>;\n\n /**\n * Make the field unique (also adds an index)\n */\n unique: DBFieldUniqueMethod<Defined, Output, Nested>;\n\n /**\n * Enable vector search on the field (string type only)\n */\n vector: DBFieldVectorMethod<Defined, Output, Nested>;\n\n /**\n * Set a default value for the field on create. When the field is required,\n * this makes it optional in the Create input — the default fills in when\n * no value (or a nullish hook result) is provided.\n *\n * For datetime/date/time fields, pass `\"now\"` to use the operation timestamp.\n */\n default: DBFieldDefaultMethod<Defined, Output, Nested>;\n\n /**\n * Add hooks for create/update operations on this field.\n */\n hooks: DBFieldHooksMethod<Defined, Output, Nested>;\n\n /**\n * Add validation functions to the field.\n *\n * Validators receive `{ value, data, user }` and run after hooks and\n * built-in type validation; they are skipped when built-in validation\n * fails. For array fields, `value` is the complete array.\n */\n validate: DBFieldValidateMethod<Defined, Output, Nested>;\n\n /**\n * Configure serial/auto-increment behavior\n */\n serial: DBFieldSerialMethod<Defined, Output, Nested>;\n\n /**\n * Clone the field with optional overrides for field options.\n * The `array` option cannot change on fields with custom validation.\n */\n clone<const NewOpt extends DBFieldCloneOptions<Defined>>(\n options?: NewOpt,\n ): TailorDBField<\n WithDBFieldCloneOptions<Defined, NewOpt>,\n DBFieldCloneOutput<Output, NewOpt>,\n Nested\n >;\n}\n\n/**\n * Full TailorDBType interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorDBType<\n // oxlint-disable-next-line no-explicit-any\n Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributes,\n // oxlint-disable-next-line no-explicit-any\n Defined extends DefinedDBTypeMetadata = any,\n FileKeys extends string = never,\n> extends TailorDBTypeBase<Fields, User> {\n _description?: string;\n\n hooks(\n hook: DBTypeDuplicateInputGuard<\n Defined,\n \"hooks\",\n TypeHook<Fields>,\n \".hooks() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"hooks\">, FileKeys>;\n validate(\n fn: DBTypeDuplicateInputGuard<\n Defined,\n \"validate\",\n TypeValidateFn<Fields>,\n \".validate() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"validate\">, FileKeys>;\n features(\n features: DBTypeDuplicateInputGuard<\n Defined,\n \"features\",\n Omit<TypeFeatures, \"pluralForm\">,\n \".features() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"features\">, FileKeys>;\n indexes(\n ...indexes: DBTypeDuplicateRestGuard<\n Defined,\n \"indexes\",\n IndexDef<TailorDBType<Fields, User, Defined, FileKeys>>[],\n \".indexes() has already been set\"\n >\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"indexes\">, FileKeys>;\n files<const F extends string>(\n files: DBTypeDuplicateInputGuard<\n Defined,\n \"files\",\n Record<F, string> & FileKeyConflictError<Fields, User>,\n \".files() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"files\">, FileKeys | F>;\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User, Defined>>> =\n TailorTypePermission<U, output<TailorDBType<Fields, User, Defined>>>,\n >(\n permission: DBTypeDuplicateInputGuard<\n Defined,\n \"permission\",\n P,\n \".permission() has already been set\"\n >,\n ): TailorDBType<Fields, U, WithDBTypeMetadata<Defined, \"permission\">, FileKeys>;\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(\n permission: DBTypeDuplicateInputGuard<\n Defined,\n \"gqlPermission\",\n P,\n \".gqlPermission() has already been set\"\n >,\n ): TailorDBType<Fields, U, WithDBTypeMetadata<Defined, \"gqlPermission\">, FileKeys>;\n description(\n description: DBTypeDuplicateInputGuard<\n Defined,\n \"description\",\n string,\n \".description() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"description\">, FileKeys>;\n pickFields<K extends keyof Fields>(keys: K[]): Pick<Fields, K>;\n pickFields<K extends keyof Fields, const Opt extends FieldOptions>(\n keys: K[],\n options: Opt & DBFieldsCloneOptionsGuard<Fields, K, Opt>,\n ): {\n [P in K]: Fields[P] extends TailorDBField<infer D, infer O>\n ? TailorDBField<WithDBFieldCloneOptions<D, Opt>, DBFieldCloneOutput<O, Opt>>\n : never;\n };\n omitFields<K extends keyof Fields>(keys: K[]): Omit<Fields, K>;\n plugin<const Config extends Record<string, unknown>>(\n config: Config & PluginConfigGuard<Fields, Config, FileKeys>,\n ): TailorDBType<PluginExtendedFields<Fields, Config>, User, Defined, FileKeys>;\n}\n\nexport type TailorDBInstance<\n // oxlint-disable-next-line no-explicit-any\n Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributes,\n // oxlint-disable-next-line no-explicit-any\n Defined extends DefinedDBTypeMetadata = any,\n FileKeys extends string = never,\n> = TailorDBType<Fields, User, Defined, FileKeys>;\n\ninterface RelationConfig<S extends RelationType, T extends TailorDBType> {\n type: S;\n toward:\n | {\n table: T;\n as?: string;\n key?: keyof T[\"fields\"] & string;\n type?: never;\n }\n | {\n /**\n * @deprecated since 2.6.0 — use `table` instead. codemod: v3/relation-toward-table\n */\n type: T;\n as?: string;\n key?: keyof T[\"fields\"] & string;\n table?: never;\n };\n backward?: string;\n}\n\n// Special config variant for self-referencing relations\ntype RelationSelfConfig = {\n type: RelationType;\n toward:\n | {\n table: \"self\";\n as?: string;\n key?: string;\n type?: never;\n }\n | {\n /**\n * @deprecated since 2.6.0 — use `table` instead. codemod: v3/relation-toward-table\n */\n type: \"self\";\n as?: string;\n key?: string;\n table?: never;\n };\n backward?: string;\n};\n\ntype DBFieldDefined<T extends TailorFieldType, Opt extends FieldOptions> = {\n type: T;\n array: Opt extends { array: true } ? true : false;\n};\ntype DBFieldOutput<\n T extends TailorFieldType,\n Opt extends FieldOptions,\n OutputBase = TailorToTs[T],\n> = FieldOutput<OutputBase, Opt>;\ntype TailorDBFieldInstance<\n T extends TailorFieldType,\n Opt extends FieldOptions,\n OutputBase = TailorToTs[T],\n> = TailorDBField<DBFieldDefined<T, Opt>, DBFieldOutput<T, Opt, OutputBase>>;\ntype TailorDBFieldRuntimeInstance<\n T extends TailorFieldType,\n Opt extends FieldOptions,\n OutputBase = TailorToTs[T],\n> = TailorDBFieldRuntime<DBFieldDefined<T, Opt>, DBFieldOutput<T, Opt, OutputBase>>;\ntype TailorDBFieldRuntime<Defined extends DefinedDBFieldMetadata, Output> = Omit<\n TailorDBFieldBase<Defined, Output>,\n \"fields\"\n> & {\n readonly fields: Record<string, TailorAnyDBField>;\n _metadata: DBFieldMetadata;\n description(description: string): object;\n typeName(typeName: string): object;\n validate(...validate: FieldValidateInput<Output>[]): object;\n relation(config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig): object;\n index(): object;\n unique(): object;\n vector(): object;\n default(value: unknown): object;\n hooks(hooks: Hook<Output>): object;\n serial(config: SerialConfig): object;\n clone(options?: FieldOptions): TailorDBFieldRuntime<DefinedDBFieldMetadata, AnyBuilderMethod>;\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n _setRawRelation(relation: RawRelationConfig): void;\n};\n\n/**\n * Creates a new TailorDBField instance.\n * @param type - Field type\n * @param options - Field options\n * @param fields - Nested fields for object-like types\n * @param values - Allowed values for enum-like fields\n * @returns A new TailorDBField\n */\nfunction createTailorDBField<\n const T extends TailorFieldType,\n const TOptions extends FieldOptions,\n const OutputBase = TailorToTs[T],\n>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyDBField>,\n values?: AllowedValues,\n): TailorDBFieldInstance<T, TOptions, OutputBase>;\nfunction createTailorDBField<const T extends TailorFieldType, const TOptions extends FieldOptions>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyDBField>,\n values?: AllowedValues,\n): object {\n return createTailorDBFieldRuntime(type, options, fields, values);\n}\n\nfunction createTailorDBFieldRuntime<\n const T extends TailorFieldType,\n const TOptions extends FieldOptions,\n const OutputBase = TailorToTs[T],\n>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyDBField>,\n values?: AllowedValues,\n): TailorDBFieldRuntimeInstance<T, TOptions, OutputBase> {\n type FieldValue = DBFieldOutput<T, TOptions, OutputBase>;\n type FieldType = TailorDBFieldRuntimeInstance<T, TOptions, OutputBase>;\n\n const _metadata: DBFieldMetadata = { required: true };\n let _rawRelation: RawRelationConfig | undefined;\n\n if (options) {\n if (options.optional === true) {\n _metadata.required = false;\n }\n if (options.array === true) {\n _metadata.array = true;\n }\n }\n if (values) {\n _metadata.allowedValues = mapAllowedValues(values);\n }\n\n function parseInternal(args: FieldParseInternalArgs): StandardSchemaV1.Result<FieldValue> {\n return parseFieldInternal<T, FieldValue>({\n ...args,\n field,\n });\n }\n\n function cloneWith(metadataUpdates: Partial<DBFieldMetadata>) {\n const cloned = field.clone();\n Object.assign(cloned._metadata, metadataUpdates);\n return cloned;\n }\n\n const field: FieldType = {\n type,\n fields: fields ?? {},\n _defined: undefined as unknown as DBFieldDefined<T, TOptions>,\n _output: undefined as FieldValue,\n _metadata,\n\n get metadata() {\n return { ...this._metadata };\n },\n\n get rawRelation(): Readonly<RawRelationConfig> | undefined {\n return _rawRelation ? { ..._rawRelation, toward: { ..._rawRelation.toward } } : undefined;\n },\n\n description(description: string) {\n return cloneWith({ description });\n },\n\n typeName(typeName: string) {\n return cloneWith({ typeName });\n },\n\n validate(...validateInputs: FieldValidateInput<FieldValue>[]) {\n return cloneWith({ validate: validateInputs });\n },\n\n parse(args: FieldParseArgs): StandardSchemaV1.Result<FieldValue> {\n return parseInternal({\n value: args.value,\n data: args.data,\n invoker: args.invoker,\n pathArray: [],\n });\n },\n\n // TailorDBField specific methods\n relation(config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig) {\n const cloned = field.clone();\n // The public type is a nested union (RelationConfig | RelationSelfConfig,\n // each with a `{ table } | { type }` toward), which TS's \"in\" narrowing\n // can't discriminate across cleanly. Re-view it as the flat two-branch\n // shape it always is at runtime — the `table?: never` / `type?: never`\n // markers above already forbid both keys from being set together.\n const toward = config.toward as\n | { table: TailorDBType | \"self\" }\n | { type: TailorDBType | \"self\" };\n const towardTarget = \"table\" in toward ? toward.table : toward.type;\n const targetTable = towardTarget === \"self\" ? \"self\" : towardTarget.name;\n cloned._setRawRelation({\n type: config.type,\n toward: {\n table: targetTable,\n as: config.toward.as,\n key: config.toward.key,\n },\n backward: config.backward,\n });\n return cloned;\n },\n\n index() {\n return cloneWith({ index: true });\n },\n\n unique() {\n return cloneWith({ unique: true, index: true });\n },\n\n vector() {\n return cloneWith({ vector: true });\n },\n\n // oxlint-disable-next-line no-explicit-any\n default(value: any) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ default: value }) as any;\n },\n\n hooks(hooks: Hook<FieldValue>) {\n return cloneWith({ hooks });\n },\n\n serial(config: SerialConfig) {\n return cloneWith({ serial: config });\n },\n\n clone(cloneOptions?: FieldOptions) {\n if (\n this._metadata.validate?.length &&\n cloneOptions?.array !== undefined &&\n cloneOptions.array !== (this._metadata.array === true)\n ) {\n throw new Error(\"Cannot change the array option on a field with custom validation\");\n }\n\n // Deep clone nested object fields if present\n let clonedFields = fields;\n if (fields) {\n const cloned: Record<string, TailorAnyDBField> = {};\n for (const [key, field] of Object.entries(fields)) {\n cloned[key] = field.clone();\n }\n clonedFields = cloned;\n }\n\n // Create a new field with cloned configuration\n const clonedField = createTailorDBFieldRuntime(type, options, clonedFields, values);\n\n // Deep copy metadata using cloneDeep (preserves function references)\n Object.assign(clonedField._metadata, cloneDeep(this._metadata));\n\n // Apply new options if provided\n if (cloneOptions) {\n if (cloneOptions.optional !== undefined) {\n clonedField._metadata.required = !cloneOptions.optional;\n }\n if (cloneOptions.array !== undefined) {\n clonedField._metadata.array = cloneOptions.array;\n }\n }\n\n // Copy raw relation if exists\n if (_rawRelation) {\n clonedField._setRawRelation(cloneDeep(_rawRelation));\n }\n\n return clonedField;\n },\n\n _setRawRelation(relation: RawRelationConfig) {\n _rawRelation = relation;\n },\n };\n\n return field;\n}\n\nconst createField = createTailorDBField;\n\n/**\n * Create a UUID field.\n * @param options - Field configuration options\n * @returns A UUID field\n * @example db.uuid()\n * @example db.uuid({ optional: true })\n */\nfunction uuid<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"uuid\", options);\n}\n\n/**\n * Create a string field.\n * @param options - Field configuration options\n * @returns A string field\n * @example db.string()\n * @example db.string({ optional: true })\n */\nfunction string<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"string\", options);\n}\n\n/**\n * Create a boolean field.\n * Note: The method name is `bool` but creates a `boolean` type field.\n * @param options - Field configuration options\n * @returns A boolean field\n * @example db.bool()\n * @example db.bool({ optional: true })\n */\nfunction bool<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"boolean\", options);\n}\n\n/**\n * Create an integer field.\n * @param options - Field configuration options\n * @returns An integer field\n * @example db.int()\n * @example db.int({ optional: true })\n */\nfunction int<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"integer\", options);\n}\n\n/**\n * Create a float (decimal number) field.\n * @param options - Field configuration options\n * @returns A float field\n * @example db.float()\n * @example db.float({ optional: true })\n */\nfunction float<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"float\", options);\n}\n\ninterface DecimalFieldOptions extends FieldOptions {\n scale?: number;\n}\n\n/**\n * Create a decimal field (stored as string for precision).\n * @param options - Field configuration options including optional scale (0-12)\n * @returns A decimal field\n * @example db.decimal()\n * @example db.decimal({ scale: 2 })\n * @example db.decimal({ scale: 2, optional: true })\n */\nfunction decimal<const Opt extends DecimalFieldOptions>(options?: Opt) {\n if (options?.scale !== undefined) {\n if (!Number.isInteger(options.scale) || options.scale < 0 || options.scale > 12) {\n throw new Error(\"scale must be an integer between 0 and 12\");\n }\n }\n const field = createField(\"decimal\", options);\n if (options?.scale !== undefined) {\n field._metadata.scale = options.scale;\n }\n return field;\n}\n\n/**\n * Create a date field (date only, no time component).\n * Format: \"yyyy-MM-dd\"\n * @param options - Field configuration options\n * @returns A date field\n * @example db.date()\n */\nfunction date<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"date\", options);\n}\n\n/**\n * Create a datetime field (date and time).\n * Format: ISO 8601, such as \"yyyy-MM-ddTHH:mm:ssZ\" or \"yyyy-MM-ddTHH:mm:ss+09:00\"\n * @param options - Field configuration options\n * @returns A datetime field\n * @example db.datetime()\n */\nfunction datetime<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"datetime\", options);\n}\n\n/**\n * Create a time field (time only, no date component).\n * Format: \"HH:mm\"\n * @param options - Field configuration options\n * @returns A time field\n * @example db.time()\n */\nfunction time<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"time\", options);\n}\n\n/**\n * Create an enum field with a fixed set of allowed string values.\n * @param values - Array of allowed string values, or array of `{ value, description }` objects\n * @param options - Field configuration options\n * @returns An enum field\n * @example db.enum([\"active\", \"inactive\", \"suspended\"])\n * @example db.enum([\"small\", \"medium\", \"large\"], { optional: true })\n */\nfunction _enum<const V extends AllowedValues, const Opt extends FieldOptions>(\n values: V,\n options?: Opt,\n): TailorDBField<\n { type: \"enum\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<AllowedValuesOutput<V>, Opt>\n> {\n return createField<\"enum\", Opt, AllowedValuesOutput<V>>(\"enum\", options, undefined, values);\n}\n\n/**\n * Create a nested object field with sub-fields.\n * @param fields - Record of nested field definitions\n * @param options - Field configuration options\n * @returns A nested object field\n * @example db.object({ street: db.string(), city: db.string(), zip: db.string() })\n * @example db.object({ name: db.string() }, { optional: true })\n */\nfunction object<\n const F extends Record<string, TailorAnyDBField> &\n ExcludeNestedDBFields<F> &\n ExcludeHookedDBFields<F> &\n ExcludeDefaultedDBFields<F>,\n const Opt extends FieldOptions,\n>(fields: F, options?: Opt) {\n return createField(\"nested\", options, fields) as unknown as TailorDBField<\n { type: \"nested\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<InferFieldsOutput<F>, Opt>,\n F\n >;\n}\n\n/**\n * Creates a new TailorDBType instance.\n * @param name - Table name\n * @param fields - Field definitions\n * @param options - Table options\n * @param options.pluralForm - Optional plural form\n * @param options.description - Optional description\n * @returns A new TailorDBType\n */\nfunction createTailorDBType<\n // oxlint-disable-next-line no-explicit-any\n const Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributes,\n>(\n name: string,\n fields: Fields,\n options: { pluralForm?: string; description?: string },\n): TailorDBType<Fields, User, DefinedDBTypeMetadata> {\n let _description = options.description;\n let _settings: TypeFeatures = {};\n let _indexes: IndexDef<TailorDBType<Fields, User, DefinedDBTypeMetadata>>[] = [];\n const _permissions: RawPermissions = {};\n let _files: Record<string, string> = {};\n const _plugins: PluginAttachment[] = [];\n // oxlint-disable-next-line typescript/no-unsafe-function-type\n let _typeHook: { create?: Function; update?: Function } | undefined;\n // oxlint-disable-next-line typescript/no-unsafe-function-type\n let _typeValidate: Function | undefined;\n const _definedMethods = new Set<keyof DefinedDBTypeMetadata>();\n if (options.description !== undefined) {\n _definedMethods.add(\"description\");\n }\n\n function runMethodOnce<T>(method: keyof DefinedDBTypeMetadata, action: () => T): T {\n if (_definedMethods.has(method)) {\n throw new Error(`.${method}() has already been set`);\n }\n const result = action();\n _definedMethods.add(method);\n return result;\n }\n type TypeAfter<Key extends keyof DefinedDBTypeMetadata> = TailorDBType<\n Fields,\n User,\n WithDBTypeMetadata<DefinedDBTypeMetadata, Key>\n >;\n type TypeAfterUser<\n NextUser extends object,\n Key extends keyof DefinedDBTypeMetadata,\n > = TailorDBType<Fields, NextUser, WithDBTypeMetadata<DefinedDBTypeMetadata, Key>>;\n type TypeAfterPlugin<Config extends Record<string, unknown>> = TailorDBType<\n PluginExtendedFields<Fields, Config>,\n User,\n DefinedDBTypeMetadata\n >;\n\n if (options.pluralForm) {\n if (name === options.pluralForm) {\n throw new Error(`The name and the plural form must be different. name=${name}`);\n }\n _settings.pluralForm = options.pluralForm;\n }\n\n const dbType: TailorDBType<Fields, User, DefinedDBTypeMetadata> = {\n name,\n fields: { ...fields },\n _output: null as unknown as InferFieldsOutput<Fields>,\n _description,\n\n get metadata(): TailorDBTypeMetadata {\n // Convert indexes to the format expected by the manifest\n const indexes: Record<string, { fields: string[]; unique?: boolean }> = {};\n if (_indexes.length > 0) {\n _indexes.forEach((index) => {\n const fieldNames = index.fields.map((field) => String(field));\n const key = index.name || `idx_${fieldNames.join(\"_\")}`;\n indexes[key] = {\n fields: fieldNames,\n unique: index.unique,\n };\n });\n }\n\n return {\n name: this.name,\n description: _description,\n settings: _settings,\n permissions: _permissions,\n files: _files,\n ...(Object.keys(indexes).length > 0 && { indexes }),\n ...(_typeHook && { typeHook: _typeHook }),\n ...(_typeValidate && { typeValidate: _typeValidate }),\n };\n },\n\n hooks(hook: TypeHook<Fields>): TypeAfter<\"hooks\"> {\n return runMethodOnce(\"hooks\", () => {\n _typeHook = hook;\n return this as TypeAfter<\"hooks\">;\n });\n },\n\n validate(fn: TypeValidateFn<Fields>): TypeAfter<\"validate\"> {\n return runMethodOnce(\"validate\", () => {\n _typeValidate = fn;\n return this as TypeAfter<\"validate\">;\n });\n },\n\n features(features: Omit<TypeFeatures, \"pluralForm\">): TypeAfter<\"features\"> {\n return runMethodOnce(\"features\", () => {\n _settings = {\n ..._settings,\n ...features,\n };\n return this as TypeAfter<\"features\">;\n });\n },\n\n indexes(\n ...indexes: IndexDef<TailorDBType<Fields, User, DefinedDBTypeMetadata>>[]\n ): TypeAfter<\"indexes\"> {\n return runMethodOnce(\"indexes\", () => {\n _indexes = indexes;\n return this as TypeAfter<\"indexes\">;\n });\n },\n\n files<const F extends string>(\n files: Record<F, string> & FileKeyConflictError<Fields, User>,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<DefinedDBTypeMetadata, \"files\">, F> {\n return runMethodOnce(\"files\", () => {\n _files = files;\n return this as TailorDBType<\n Fields,\n User,\n WithDBTypeMetadata<DefinedDBTypeMetadata, \"files\">,\n F\n >;\n });\n },\n\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User, DefinedDBTypeMetadata>>> =\n TailorTypePermission<U, output<TailorDBType<Fields, User, DefinedDBTypeMetadata>>>,\n >(permission: P): TypeAfterUser<U, \"permission\"> {\n return runMethodOnce(\"permission\", () => {\n const ret = this as unknown as TypeAfterUser<U, \"permission\">;\n _permissions.record = permission as RawPermissions[\"record\"];\n return ret;\n });\n },\n\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(permission: P): TypeAfterUser<U, \"gqlPermission\"> {\n return runMethodOnce(\"gqlPermission\", () => {\n const ret = this as unknown as TypeAfterUser<U, \"gqlPermission\">;\n _permissions.gql = permission as RawPermissions[\"gql\"];\n return ret;\n });\n },\n\n description(description: string): TypeAfter<\"description\"> {\n return runMethodOnce(\"description\", () => {\n _description = description;\n this._description = description;\n return this as TypeAfter<\"description\">;\n });\n },\n\n pickFields<K extends keyof Fields, const Opt extends FieldOptions>(keys: K[], options?: Opt) {\n const result = {} as Record<K, TailorAnyDBField>;\n for (const key of keys) {\n const field = this.fields[key] as TailorAnyDBField | undefined;\n if (!field) {\n // A plugin-injected field is only added to `fields` after `tailor\n // generate` runs — see the \"Injecting fields into the attached\n // table's type\" section of the plugin docs.\n throw new Error(\n `pickFields(): field \"${String(key)}\" does not exist on this table yet. If it comes from a plugin's .plugin() call, it is only added to the table after \\`tailor generate\\` runs.`,\n );\n }\n if (options) {\n result[key] = field.clone(options);\n } else {\n result[key] = field;\n }\n }\n // oxlint-disable-next-line no-explicit-any\n return result as any;\n },\n\n omitFields<K extends keyof Fields>(keys: K[]): Omit<Fields, K> {\n const keysSet = new Set(keys);\n const result = {} as Record<string, TailorAnyDBField>;\n for (const key in this.fields) {\n if (Object.hasOwn(this.fields, key) && !keysSet.has(key as unknown as K)) {\n result[key] = this.fields[key] as TailorAnyDBField;\n }\n }\n return result as Omit<Fields, K>;\n },\n\n get plugins(): PluginAttachment[] {\n return _plugins;\n },\n\n plugin<const Config extends Record<string, unknown>>(\n config: Config & PluginConfigGuard<Fields, Config, never>,\n ): TypeAfterPlugin<Config> {\n for (const [pluginId, pluginConfig] of Object.entries(config)) {\n _plugins.push({ pluginId, config: pluginConfig });\n }\n return this as unknown as TypeAfterPlugin<Config>;\n },\n };\n\n return brandValue(dbType, \"tailordb-type\");\n}\n\nconst idField = uuid();\ntype idField = typeof idField;\ntype DBTable<\n F extends { id?: never } & Record<string, TailorAnyDBField>,\n Defined extends DefinedDBTypeMetadata = DefinedDBTypeMetadata,\n> = TailorDBInstance<{ id: idField } & F, InferredAttributes, Defined>;\n\n/**\n * Creates a new database table with the specified fields.\n * An `id` field (UUID) is automatically added to every table.\n * @param name - The name of the table, or a tuple of [name, pluralForm]\n * @param fields - The field definitions for the table\n * @returns A new TailorDB table instance\n * @example\n * export const user = db.table(\"User\", {\n * name: db.string(),\n * email: db.string(),\n * age: db.int({ optional: true }),\n * role: db.enum([\"admin\", \"member\"]),\n * ...db.fields.timestamps(),\n * });\n * // Always export both the value and type:\n * export type user = typeof user;\n */\nfunction dbTable<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fields: F,\n): DBTable<F>;\n/**\n * Creates a new database table with the specified fields and description.\n * An `id` field (UUID) is automatically added to every table.\n * @param name - The name of the table, or a tuple of [name, pluralForm]\n * @param description - A description of the table\n * @param fields - The field definitions for the table\n * @returns A new TailorDB table instance\n */\nfunction dbTable<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n description: string,\n fields: F,\n): DBTable<F, WithDBTypeMetadata<DefinedDBTypeMetadata, \"description\">>;\nfunction dbTable<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fieldsOrDescription: string | F,\n fields?: F,\n): DBTable<F> | DBTable<F, WithDBTypeMetadata<DefinedDBTypeMetadata, \"description\">> {\n const typeName = Array.isArray(name) ? name[0] : name;\n const pluralForm = Array.isArray(name) ? name[1] : undefined;\n\n let description: string | undefined;\n let fieldDef: F;\n if (typeof fieldsOrDescription === \"string\") {\n description = fieldsOrDescription;\n fieldDef = fields as F;\n } else {\n fieldDef = fieldsOrDescription;\n }\n return createTailorDBType<{ id: idField } & F>(\n typeName,\n {\n id: idField,\n ...fieldDef,\n },\n { pluralForm, description },\n );\n}\n\n// `Function.prototype.toString()` of this hook is embedded verbatim into deployed\n// schemas and migration diffs (see parser/service/tailordb/hooks-validate-precompiled-expr.ts\n// and field.ts). Its source text depends on how the SDK itself was built (e.g.\n// minification), so a fixed expression is pinned onto it directly here instead -\n// configure cannot import parser's `setPrecompiledScriptExpr` runtime helper across\n// the module boundary, only the symbol registry key and map types. Keep\n// this literal in sync with the \"timestamps() updatedAt hook resolves to the pinned\n// expr\" test in parser/service/tailordb/field.precompiled.test.ts, which fails if it\n// ever drifts from what this hook's own source naturally produces.\ntype TimestampsUpdatedAtHookFn = UpdateHookFn<string | Date | null, string | Date>;\nconst timestampsUpdatedAtHook: TimestampsUpdatedAtHookFn = ({ input, now }) => input ?? now;\nconst PRECOMPILED_EXPR_KEY: PrecompiledScriptExprKey =\n \"tailor-platform/sdk:precompiled-script-expr\";\nconst PRECOMPILED_EXPR_SYMBOL = Symbol.for(PRECOMPILED_EXPR_KEY);\n(timestampsUpdatedAtHook as unknown as Record<symbol, PrecompiledScriptExprMap>)[\n PRECOMPILED_EXPR_SYMBOL\n] = {\n \"hooks.update\":\n \"(({ input, now }) => input ?? now)({ input: _value, oldValue: _oldValue, invoker: _principal, now: _now })\",\n};\n\n/** TailorDB schema builder utilities for defining tables and fields. */\nexport const db = {\n table: dbTable,\n uuid,\n string,\n bool,\n int,\n float,\n decimal,\n date,\n datetime,\n time,\n enum: _enum,\n object,\n fields: {\n /**\n * Creates standard timestamp fields (createdAt, updatedAt) with automatic defaults.\n * Both fields default to the current time on create. updatedAt is also refreshed on update.\n * User-specified values are respected when provided (e.g. seeding historical records).\n * @returns An object with createdAt and updatedAt fields\n * @example\n * const model = db.table(\"Model\", {\n * name: db.string(),\n * ...db.fields.timestamps(),\n * });\n */\n timestamps: () => ({\n createdAt: datetime().default(\"now\").description(\"Record creation timestamp\"),\n updatedAt: datetime()\n .default(\"now\")\n .hooks({ update: timestampsUpdatedAtHook })\n .description(\"Record update timestamp\"),\n }),\n },\n};\n"],"mappings":"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"}
|
|
@@ -65,30 +65,53 @@ import{t as e}from"./assert-WeXvmG4j.mjs";import{t}from"./multiline-EyzjEwn9.mjs
|
|
|
65
65
|
errors,
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
|
-
`}
|
|
68
|
+
`}const i=t`
|
|
69
|
+
async function listUsers(client) {
|
|
70
|
+
let after = undefined;
|
|
71
|
+
const users = [];
|
|
72
|
+
do {
|
|
73
|
+
const response = await client.users(after ? { after } : undefined);
|
|
74
|
+
for (const user of response.users || []) {
|
|
75
|
+
users.push({ id: user.id, name: user.name });
|
|
76
|
+
}
|
|
77
|
+
after = response.nextPageToken;
|
|
78
|
+
} while (after);
|
|
79
|
+
console.log(\`Found \${users.length} IDP users to delete\`);
|
|
80
|
+
return users;
|
|
81
|
+
}
|
|
82
|
+
`;function generateIdpListUsersScriptCode(e){return t`
|
|
83
|
+
${i}
|
|
84
|
+
|
|
69
85
|
export async function main() {
|
|
86
|
+
const client = new tailor.idp.Client({ namespace: "${e}" });
|
|
87
|
+
const users = await listUsers(client);
|
|
88
|
+
return { success: true, users };
|
|
89
|
+
}
|
|
90
|
+
`}function generateIdpTruncateScriptCode(e){return t`
|
|
91
|
+
${i}
|
|
92
|
+
|
|
93
|
+
export async function main(input) {
|
|
70
94
|
const client = new tailor.idp.Client({ namespace: "${e}" });
|
|
71
95
|
const errors = [];
|
|
72
96
|
let deleted = 0;
|
|
97
|
+
let notFound = 0;
|
|
98
|
+
const users = Array.isArray(input.users) ? input.users : await listUsers(client);
|
|
99
|
+
const offset = typeof input.offset === "number" ? input.offset : 0;
|
|
100
|
+
const total = typeof input.total === "number" ? input.total : users.length;
|
|
73
101
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const allUsers = [];
|
|
77
|
-
do {
|
|
78
|
-
const response = await client.users(after ? { after } : undefined);
|
|
79
|
-
allUsers.push(...(response.users || []));
|
|
80
|
-
after = response.nextPageToken;
|
|
81
|
-
} while (after);
|
|
82
|
-
|
|
83
|
-
console.log(\`Found \${allUsers.length} IDP users to delete\`);
|
|
84
|
-
|
|
85
|
-
for (const user of allUsers) {
|
|
102
|
+
for (let i = 0; i < users.length; i++) {
|
|
103
|
+
const user = users[i];
|
|
86
104
|
try {
|
|
87
105
|
await client.deleteUser(user.id);
|
|
88
106
|
deleted++;
|
|
89
|
-
console.log(\`[_User] Deleted \${
|
|
107
|
+
console.log(\`[_User] Deleted \${offset + i + 1}/\${total}: \${user.name}\`);
|
|
90
108
|
} catch (error) {
|
|
91
109
|
const message = error instanceof Error ? error.message : String(error);
|
|
110
|
+
if (/user not found/i.test(message)) {
|
|
111
|
+
notFound++;
|
|
112
|
+
console.log(\`[_User] Already deleted \${offset + i + 1}/\${total}: \${user.name}\`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
92
115
|
errors.push(\`User \${user.id} (\${user.name}): \${message}\`);
|
|
93
116
|
console.error(\`[_User] Delete failed for \${user.name}: \${message}\`);
|
|
94
117
|
}
|
|
@@ -97,7 +120,8 @@ import{t as e}from"./assert-WeXvmG4j.mjs";import{t}from"./multiline-EyzjEwn9.mjs
|
|
|
97
120
|
return {
|
|
98
121
|
success: errors.length === 0,
|
|
99
122
|
deleted,
|
|
100
|
-
|
|
123
|
+
notFound,
|
|
124
|
+
total: users.length,
|
|
101
125
|
errors,
|
|
102
126
|
};
|
|
103
127
|
}
|
|
@@ -203,5 +227,5 @@ import{t as e}from"./assert-WeXvmG4j.mjs";import{t}from"./multiline-EyzjEwn9.mjs
|
|
|
203
227
|
createStandardSchema(schemaType, hook, ${i}),${p}
|
|
204
228
|
);
|
|
205
229
|
|
|
206
|
-
`}const
|
|
207
|
-
//# sourceMappingURL=seed-
|
|
230
|
+
`}const a=`@tailor-platform/seed`;function resolveIdpUserSyncFKs(e){return{emitUserToIdpFK:!(e?.userToIdp??!1),emitIdpToUserFK:!(e?.idpToUser??!1)}}function seedPlugin(t){return{id:a,description:`Generates seed data and schema files for the tailor seed CLI plugin`,pluginConfig:t,async onTailorDBReady(t){let n=[],i=t.auth?processIdpUser(t.auth)??null:null,a=resolveIdpUserSyncFKs(t.pluginConfig.disableIdpUserSync);for(let o of t.tailordb)for(let[s,c]of Object.entries(o.tables)){let l=processLinesDb(c,e(o.sourceInfo.get(s),`source info missing for table: ${s}`));a.emitUserToIdpFK&&i&&s===i.schema.userTableName&&l.foreignKeys.push({column:i.schema.usernameField,references:{table:`_User`,column:`name`}}),n.push({path:r.join(t.pluginConfig.distPath,`data`,`${l.tableName}.jsonl`),content:``,skipIfExists:!0});let u=r.join(t.pluginConfig.distPath,`data`,`${l.tableName}.schema.ts`);if(l.pluginSource&&l.pluginSource.pluginImportPath){let e;if(l.pluginSource.originalFilePath&&l.pluginSource.originalExportName){let t=r.relative(r.dirname(u),l.pluginSource.originalFilePath);e=t.replace(/\.ts$/,``).startsWith(`.`)?t.replace(/\.ts$/,``):`./${t.replace(/\.ts$/,``)}`}let i=generateLinesDbSchemaFileWithPluginAPI(l,{configImportPath:r.relative(r.dirname(u),t.configPath),originalImportPath:e});n.push({path:u,content:i})}else{let e=r.relative(r.dirname(u),l.importPath),t=generateLinesDbSchemaFile(l,e.replace(/\.ts$/,``).startsWith(`.`)?e.replace(/\.ts$/,``):`./${e.replace(/\.ts$/,``)}`);n.push({path:u,content:t})}}return i&&(n.push({path:r.join(t.pluginConfig.distPath,i.dataFile),content:``,skipIfExists:!0}),n.push({path:r.join(t.pluginConfig.distPath,`data`,`${i.name}.schema.ts`),content:generateIdpUserSchemaFile({usernameField:i.schema.usernameField,userTableName:i.schema.userTableName,includeUserProfileFK:a.emitIdpToUserFK})})),{files:n}}}}export{generateIdpSeedScriptCode as a,generateIdpListUsersScriptCode as i,seedPlugin as n,generateIdpTruncateScriptCode as o,processLinesDb as r,processIdpUser as s,a as t};
|
|
231
|
+
//# sourceMappingURL=seed-CMkupmX8.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-CMkupmX8.mjs","names":[],"sources":["../src/plugin/builtin/seed/idp-user-processor.ts","../src/plugin/builtin/seed/lines-db-processor.ts","../src/plugin/builtin/seed/index.ts"],"sourcesContent":["import ml from \"#/utils/multiline\";\nimport type { GeneratorAuthInput } from \"#/plugin/types\";\n\nexport interface IdpUserMetadata {\n name: \"_User\";\n dependencies: string[];\n dataFile: string;\n idpNamespace: string;\n schema: {\n usernameField: string;\n userTableName: string;\n };\n}\n\n/**\n * Processes auth configuration to generate IdP user seed metadata\n * @param auth - Auth configuration from generator\n * @returns IdP user metadata or undefined if not applicable\n */\nexport function processIdpUser(auth: GeneratorAuthInput): IdpUserMetadata | undefined {\n // Only process if idProvider is BuiltInIdP and userProfile is defined\n if (auth.idProvider?.kind !== \"BuiltInIdP\" || !auth.userProfile) {\n return undefined;\n }\n\n const { tableName, usernameField } = auth.userProfile;\n\n return {\n name: \"_User\",\n dependencies: [tableName],\n dataFile: \"data/_User.jsonl\",\n idpNamespace: auth.idProvider.namespace,\n schema: {\n usernameField,\n userTableName: tableName,\n },\n };\n}\n\n/**\n * Generates the server-side IDP seed script code for testExecScript execution.\n * Uses the global tailor.idp.Client - no bundling required.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpSeedScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n export async function main(input) {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const errors = [];\n let processed = 0;\n let created = 0;\n let updated = 0;\n let skipped = 0;\n const upsert = input.upsert === true;\n // Rows may arrive as one chunk of a larger dataset; report row numbers\n // relative to the whole dataset so they match the source JSONL.\n const offset = typeof input.offset === \"number\" ? input.offset : 0;\n const total = typeof input.total === \"number\" ? input.total : input.users.length;\n\n for (let i = 0; i < input.users.length; i++) {\n try {\n if (upsert) {\n let existing;\n let lookupError;\n try {\n existing = await client.userByName(input.users[i].name);\n } catch (error) {\n existing = undefined;\n lookupError = error instanceof Error ? error.message : String(error);\n }\n\n if (existing) {\n const { name, ...attributes } = input.users[i];\n if (Object.keys(attributes).length === 0) {\n skipped++;\n } else {\n await client.updateUser({ id: existing.id, ...attributes });\n updated++;\n }\n } else {\n try {\n await client.createUser(input.users[i]);\n created++;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n lookupError ? \\`create failed (\\${message}); lookup failed (\\${lookupError})\\` : message,\n );\n }\n }\n } else {\n await client.createUser(input.users[i]);\n created++;\n }\n processed++;\n console.log(\\`[_User] \\${offset + i + 1}/\\${total}: \\${input.users[i].name}\\`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push(\\`Row \\${offset + i + 1} (\\${input.users[i].name}): \\${message}\\`);\n console.error(\\`[_User] Row \\${offset + i + 1} failed: \\${message}\\`);\n }\n }\n\n return {\n success: errors.length === 0,\n processed,\n created,\n updated,\n skipped,\n errors,\n };\n }\n `;\n}\n\nconst listIdpUsersFunction = ml /* ts */ `\n async function listUsers(client) {\n let after = undefined;\n const users = [];\n do {\n const response = await client.users(after ? { after } : undefined);\n for (const user of response.users || []) {\n users.push({ id: user.id, name: user.name });\n }\n after = response.nextPageToken;\n } while (after);\n console.log(\\`Found \\${users.length} IDP users to delete\\`);\n return users;\n }\n`;\n\n/**\n * Generates the server-side script that lists every IdP user for truncation.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpListUsersScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n ${listIdpUsersFunction}\n\n export async function main() {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const users = await listUsers(client);\n return { success: true, users };\n }\n `;\n}\n\n/**\n * Generates the server-side IDP truncation script code for testExecScript execution.\n * Deletes the users passed in `input.users` (one chunk of the listing produced by\n * {@link generateIdpListUsersScriptCode}), or every user when no chunk is passed so\n * older seed plugins that call it without input keep working. A user that is already\n * gone counts as deleted.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpTruncateScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n ${listIdpUsersFunction}\n\n export async function main(input) {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const errors = [];\n let deleted = 0;\n let notFound = 0;\n const users = Array.isArray(input.users) ? input.users : await listUsers(client);\n const offset = typeof input.offset === \"number\" ? input.offset : 0;\n const total = typeof input.total === \"number\" ? input.total : users.length;\n\n for (let i = 0; i < users.length; i++) {\n const user = users[i];\n try {\n await client.deleteUser(user.id);\n deleted++;\n console.log(\\`[_User] Deleted \\${offset + i + 1}/\\${total}: \\${user.name}\\`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/user not found/i.test(message)) {\n notFound++;\n console.log(\\`[_User] Already deleted \\${offset + i + 1}/\\${total}: \\${user.name}\\`);\n continue;\n }\n errors.push(\\`User \\${user.id} (\\${user.name}): \\${message}\\`);\n console.error(\\`[_User] Delete failed for \\${user.name}: \\${message}\\`);\n }\n }\n\n return {\n success: errors.length === 0,\n deleted,\n notFound,\n total: users.length,\n errors,\n };\n }\n `;\n}\n\ntype GenerateIdpUserSchemaFileOptions = {\n usernameField: string;\n userTableName: string;\n /**\n * When `true` (default), emit a foreign key from `_User.name` to the\n * userProfile table's username field so that seed validation rejects `_User`\n * rows without a matching userProfile row. Set to `false` to seed `_User`\n * rows that do not yet have a corresponding userProfile row.\n */\n includeUserProfileFK?: boolean;\n};\n\n/**\n * Generates the schema file content for IdP users. Emits the\n * `_User.name -> <userProfile>.<usernameField>` foreign key by default; pass\n * `includeUserProfileFK: false` to omit it (e.g. when seeding `_User` rows\n * that do not yet have a corresponding userProfile row).\n * @param options - Schema generation options\n * @param options.usernameField - Username field name\n * @param options.userTableName - TailorDB user table name\n * @param options.includeUserProfileFK - Whether to emit the `_User -> userProfile` foreign key (default `true`)\n * @returns Schema file contents\n */\nexport function generateIdpUserSchemaFile(options: GenerateIdpUserSchemaFileOptions): string {\n const { usernameField, userTableName, includeUserProfileFK = true } = options;\n const schemaBody = includeUserProfileFK\n ? ml`\n primaryKey: \"name\",\n indexes: [\n { name: \"_user_name_unique_idx\", columns: [\"name\"], unique: true },\n ],\n foreignKeys: [\n {\n column: \"name\",\n references: {\n table: \"${userTableName}\",\n column: \"${usernameField}\",\n },\n },\n ],\n `\n : ml`\n primaryKey: \"name\",\n indexes: [\n { name: \"_user_name_unique_idx\", columns: [\"name\"], unique: true },\n ],\n `;\n\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createStandardSchema } from \"@tailor-platform/sdk/test\";\n\n const schemaType = t.object({\n name: t.string(),\n password: t.string(),\n });\n\n // Simple identity hook for _User (no TailorDB backing table)\n export const hook = <T>(data: unknown) => data as T;\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),\n {\n ${schemaBody}\n }\n );\n\n `;\n}\n","import { isPluginGeneratedTable } from \"#/parser/service/tailordb/type-source\";\nimport ml from \"#/utils/multiline\";\nimport type {\n PluginGeneratedTableSource,\n TailorDBType,\n TypeSourceInfoEntry,\n} from \"#/parser/service/tailordb/types\";\nimport type { LinesDbMetadata } from \"./types\";\nimport type { ForeignKeyDefinition, IndexDefinition } from \"@toiroakr/lines-db\";\n\n/**\n * Processes TailorDB tables to generate lines-db metadata\n * @param type - Parsed TailorDB table\n * @param source - Source file info\n * @returns Generated lines-db metadata\n */\nexport function processLinesDb(type: TailorDBType, source: TypeSourceInfoEntry): LinesDbMetadata {\n if (isPluginGeneratedTable(source)) {\n // Plugin-generated table\n return processLinesDbForPluginTable(type, source);\n }\n\n // User-defined table\n if (!source.filePath) {\n throw new Error(`Missing source info for table ${type.name}`);\n }\n if (!source.exportName) {\n throw new Error(`Missing export name for table ${type.name}`);\n }\n\n const { optionalFields, omitFields, indexes, foreignKeys } = extractFieldMetadata(type);\n\n return {\n tableName: type.name,\n exportName: source.exportName,\n importPath: source.filePath,\n optionalFields,\n omitFields,\n foreignKeys,\n indexes,\n };\n}\n\n/**\n * Process lines-db metadata for plugin-generated tables\n * @param type - Parsed TailorDB table\n * @param source - Plugin-generated table source info\n * @returns Generated lines-db metadata with plugin source\n */\nfunction processLinesDbForPluginTable(\n type: TailorDBType,\n source: PluginGeneratedTableSource,\n): LinesDbMetadata {\n const { optionalFields, omitFields, indexes, foreignKeys } = extractFieldMetadata(type);\n\n return {\n tableName: type.name,\n exportName: source.exportName,\n importPath: \"\",\n optionalFields,\n omitFields,\n foreignKeys,\n indexes,\n pluginSource: source,\n };\n}\n\n/**\n * Extract field metadata from TailorDB table\n * @param type - Parsed TailorDB table\n * @returns Field metadata including optional fields, omit fields, indexes, and foreign keys\n */\nfunction extractFieldMetadata(type: TailorDBType): {\n optionalFields: string[];\n omitFields: string[];\n indexes: IndexDefinition[];\n foreignKeys: ForeignKeyDefinition[];\n} {\n const optionalFields = [\"id\"]; // id is always optional\n const omitFields: string[] = [];\n const indexes: IndexDefinition[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n\n // Find fields with hooks.create or serial\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.config.hooks?.create) {\n optionalFields.push(fieldName);\n }\n // Serial fields are auto-generated, so they should be optional in seed data\n if (field.config.serial) {\n omitFields.push(fieldName);\n }\n if (field.config.unique) {\n indexes.push({\n name: `${type.name.toLowerCase()}_${fieldName}_unique_idx`,\n columns: [fieldName],\n unique: true,\n });\n }\n }\n\n // Extract indexes\n if (type.indexes) {\n for (const [indexName, indexDef] of Object.entries(type.indexes)) {\n indexes.push({\n name: indexName,\n columns: indexDef.fields,\n unique: indexDef.unique,\n });\n }\n }\n\n // Extract foreign keys from relations\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.relation) {\n foreignKeys.push({\n column: fieldName,\n references: {\n table: field.relation.targetType,\n column: field.relation.key,\n },\n });\n }\n }\n\n return { optionalFields, omitFields, indexes, foreignKeys };\n}\n\n/**\n * Generate schema options code for lines-db\n * @param foreignKeys - Foreign key definitions\n * @param indexes - Index definitions\n * @returns Schema options code string\n */\nfunction generateSchemaOptions(\n foreignKeys: ForeignKeyDefinition[],\n indexes: IndexDefinition[],\n): string {\n const schemaOptions: string[] = [];\n\n if (foreignKeys.length > 0) {\n schemaOptions.push(`foreignKeys: [`);\n foreignKeys.forEach((fk) => {\n schemaOptions.push(` ${JSON.stringify(fk)},`);\n });\n schemaOptions.push(`],`);\n }\n\n if (indexes.length > 0) {\n schemaOptions.push(`indexes: [`);\n indexes.forEach((index) => {\n schemaOptions.push(` ${JSON.stringify(index)},`);\n });\n schemaOptions.push(\"],\");\n }\n\n return schemaOptions.length > 0\n ? [\"\\n {\", ...schemaOptions.map((option) => ` ${option}`), \" }\"].join(\"\\n\")\n : \"\";\n}\n\n/**\n * Generates the schema file content for lines-db (for user-defined tables with import)\n * @param metadata - lines-db metadata\n * @param importPath - Import path for the TailorDB table\n * @returns Schema file contents\n */\nexport function generateLinesDbSchemaFile(metadata: LinesDbMetadata, importPath: string): string {\n const { exportName, optionalFields, omitFields, foreignKeys, indexes } = metadata;\n\n const schemaTypeCode = ml /* ts */ `\n const schemaType = t.object({\n ...${exportName}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),\n ...${exportName}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),\n });\n `;\n\n const schemaOptionsCode = generateSchemaOptions(foreignKeys, indexes);\n\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { ${exportName} } from \"${importPath}\";\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n}\n\n/**\n * Parameters for generating a plugin-generated table's schema file\n */\nexport interface PluginSchemaParams {\n /** Relative path from schema output to tailor.config.ts */\n configImportPath: string;\n /** Relative import path to the original table file (for table-attached plugins) */\n originalImportPath?: string;\n}\n\n/**\n * Generates the schema file content using getGeneratedTable API\n * (for plugin-generated tables)\n * @param metadata - lines-db metadata (must have pluginSource)\n * @param params - Plugin import paths\n * @returns Schema file contents\n */\nexport function generateLinesDbSchemaFileWithPluginAPI(\n metadata: LinesDbMetadata,\n params: PluginSchemaParams,\n): string {\n const { tableName, exportName, optionalFields, omitFields, foreignKeys, indexes, pluginSource } =\n metadata;\n\n if (!pluginSource) {\n throw new Error(`pluginSource is required for plugin-generated table \"${tableName}\"`);\n }\n\n const { configImportPath, originalImportPath } = params;\n\n const schemaTypeCode = ml /* ts */ `\n const schemaType = t.object({\n ...${exportName}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),\n ...${exportName}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),\n });\n `;\n\n const schemaOptionsCode = generateSchemaOptions(foreignKeys, indexes);\n\n // Table-attached plugin (e.g., changeset): import the original table and use getGeneratedTable(configPath, pluginId, table, kind)\n if (pluginSource.originalExportName && originalImportPath && pluginSource.generatedTableKind) {\n return ml /* ts */ `\n import { join } from \"node:path\";\n import { t } from \"@tailor-platform/sdk\";\n import { getGeneratedTable } from \"@tailor-platform/sdk/plugin\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { ${pluginSource.originalExportName} } from \"${originalImportPath}\";\n\n const configPath = join(import.meta.dirname, \"${configImportPath}\");\n const ${exportName} = await getGeneratedTable(configPath, \"${pluginSource.pluginId}\", ${pluginSource.originalExportName}, \"${pluginSource.generatedTableKind}\");\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n }\n\n // Namespace plugin (e.g., audit-log): use getGeneratedTable(configPath, pluginId, null, kind)\n // For namespace plugins, generatedTableKind is required\n if (!pluginSource.generatedTableKind) {\n throw new Error(\n `Namespace plugin \"${pluginSource.pluginId}\" must provide generatedTableKind for table \"${tableName}\"`,\n );\n }\n\n return ml /* ts */ `\n import { join } from \"node:path\";\n import { t } from \"@tailor-platform/sdk\";\n import { getGeneratedTable } from \"@tailor-platform/sdk/plugin\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n\n const configPath = join(import.meta.dirname, \"${configImportPath}\");\n const ${exportName} = await getGeneratedTable(configPath, \"${pluginSource.pluginId}\", null, \"${pluginSource.generatedTableKind}\");\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n}\n","import * as path from \"pathe\";\nimport { assertDefined } from \"#/utils/assert\";\nimport { processIdpUser, generateIdpUserSchemaFile } from \"./idp-user-processor\";\nimport {\n processLinesDb,\n generateLinesDbSchemaFile,\n generateLinesDbSchemaFileWithPluginAPI,\n type PluginSchemaParams,\n} from \"./lines-db-processor\";\nimport type { Plugin, GeneratorResult, TailorDBReadyContext } from \"#/plugin/types\";\n\n/** Unique identifier for the seed generator plugin. */\nexport const SeedGeneratorID = \"@tailor-platform/seed\";\n\ntype DisableIdpUserSyncDirections = {\n /**\n * Skip emitting the foreign key from `<userProfile>.<usernameField>` to\n * `_User.name`. Defaults to `false` (FK emitted).\n *\n * Set to `true` to seed pre-registration states such as\n * invited-but-not-registered users.\n */\n userToIdp?: boolean;\n /**\n * Skip emitting the foreign key from `_User.name` to\n * `<userProfile>.<usernameField>`. Defaults to `false` (FK emitted).\n *\n * Set to `true` to seed `_User` rows that do not yet have a corresponding\n * userProfile row.\n */\n idpToUser?: boolean;\n};\n\nexport type SeedPluginOptions = {\n distPath: string;\n machineUserName?: string;\n /**\n * Disable individual `_User <-> userProfile` foreign keys emitted into\n * the generated seed schema. Both directions are emitted by default.\n *\n * Set a direction to `true` to relax it — for example to seed invited\n * users that do not yet have an IdP credential.\n */\n disableIdpUserSync?: DisableIdpUserSyncDirections;\n};\n\ndeclare module \"@tailor-platform/sdk/plugin\" {\n interface PluginConfigRegistry {\n \"@tailor-platform/seed\": SeedPluginOptions;\n }\n}\n\nfunction resolveIdpUserSyncFKs(option: SeedPluginOptions[\"disableIdpUserSync\"]): {\n emitUserToIdpFK: boolean;\n emitIdpToUserFK: boolean;\n} {\n return {\n emitUserToIdpFK: !(option?.userToIdp ?? false),\n emitIdpToUserFK: !(option?.idpToUser ?? false),\n };\n}\n/**\n * Plugin that generates seed data and schema files consumed by the\n * `tailor seed` commands (@tailor-platform/sdk-plugin-seed).\n * @param options - Plugin options\n * @param options.distPath - Output directory path for generated seed files\n * @param options.machineUserName - Default machine user name for authentication\n * @param options.disableIdpUserSync - Skip emitting individual `_User <-> userProfile` foreign keys. Both directions are emitted by default; set a direction to `true` to relax that side.\n * @returns Plugin instance with onTailorDBReady hook\n */\nexport function seedPlugin(options: SeedPluginOptions): Plugin<unknown, SeedPluginOptions> {\n return {\n id: SeedGeneratorID,\n description: \"Generates seed data and schema files for the tailor seed CLI plugin\",\n pluginConfig: options,\n\n async onTailorDBReady(ctx: TailorDBReadyContext<SeedPluginOptions>): Promise<GeneratorResult> {\n const files: GeneratorResult[\"files\"] = [];\n\n // Process IdP user early so we can add reverse FK to the user profile type\n const idpUser = ctx.auth ? (processIdpUser(ctx.auth) ?? null) : null;\n const idpUserSyncFKs = resolveIdpUserSyncFKs(ctx.pluginConfig.disableIdpUserSync);\n\n for (const ns of ctx.tailordb) {\n for (const [tableName, type] of Object.entries(ns.tables)) {\n const source = assertDefined(\n ns.sourceInfo.get(tableName),\n `source info missing for table: ${tableName}`,\n );\n const linesDb = processLinesDb(type, source);\n\n // Add reverse FK from userProfile table to _User (opt-out via disableIdpUserSync.userToIdp: true)\n if (\n idpUserSyncFKs.emitUserToIdpFK &&\n idpUser &&\n tableName === idpUser.schema.userTableName\n ) {\n linesDb.foreignKeys.push({\n column: idpUser.schema.usernameField,\n references: {\n table: \"_User\",\n column: \"name\",\n },\n });\n }\n\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${linesDb.tableName}.jsonl`),\n content: \"\",\n skipIfExists: true,\n });\n\n const schemaOutputPath = path.join(\n ctx.pluginConfig.distPath,\n \"data\",\n `${linesDb.tableName}.schema.ts`,\n );\n\n // Plugin-generated table: use getGeneratedTable API\n if (linesDb.pluginSource && linesDb.pluginSource.pluginImportPath) {\n // Build original type import path\n let originalImportPath: string | undefined;\n if (linesDb.pluginSource.originalFilePath && linesDb.pluginSource.originalExportName) {\n const relativePath = path.relative(\n path.dirname(schemaOutputPath),\n linesDb.pluginSource.originalFilePath,\n );\n originalImportPath = relativePath.replace(/\\.ts$/, \"\").startsWith(\".\")\n ? relativePath.replace(/\\.ts$/, \"\")\n : `./${relativePath.replace(/\\.ts$/, \"\")}`;\n }\n\n // Compute relative path from schema output to config file\n const configImportPath = path.relative(path.dirname(schemaOutputPath), ctx.configPath);\n\n const params: PluginSchemaParams = {\n configImportPath,\n originalImportPath,\n };\n\n const schemaContent = generateLinesDbSchemaFileWithPluginAPI(linesDb, params);\n\n files.push({\n path: schemaOutputPath,\n content: schemaContent,\n });\n } else {\n // User-defined type: import from source file\n const relativePath = path.relative(path.dirname(schemaOutputPath), linesDb.importPath);\n const typeImportPath = relativePath.replace(/\\.ts$/, \"\").startsWith(\".\")\n ? relativePath.replace(/\\.ts$/, \"\")\n : `./${relativePath.replace(/\\.ts$/, \"\")}`;\n const schemaContent = generateLinesDbSchemaFile(linesDb, typeImportPath);\n\n files.push({\n path: schemaOutputPath,\n content: schemaContent,\n });\n }\n }\n }\n\n if (idpUser) {\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, idpUser.dataFile),\n content: \"\",\n skipIfExists: true,\n });\n\n // Generate schema file with foreign key (opt-out via disableIdpUserSync.idpToUser: true)\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${idpUser.name}.schema.ts`),\n content: generateIdpUserSchemaFile({\n usernameField: idpUser.schema.usernameField,\n userTableName: idpUser.schema.userTableName,\n includeUserProfileFK: idpUserSyncFKs.emitIdpToUserFK,\n }),\n });\n }\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
|
package/dist/types/helpers.d.mts
CHANGED
|
@@ -3,6 +3,8 @@ type Prettify<T> = { [K in keyof T as string extends K ? never : K]: T[K]; } & {
|
|
|
3
3
|
type TypeLevelError<Message extends string> = {
|
|
4
4
|
readonly $error: Message;
|
|
5
5
|
};
|
|
6
|
+
type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
|
|
7
|
+
type IsUnion<T, U extends T = T> = T extends unknown ? [U] extends [T] ? false : true : never;
|
|
6
8
|
type DeepWritable<T> = T extends Date | RegExp | Function ? T : T extends object ? { -readonly [P in keyof T]: DeepWritable<T[P]>; } & {} : T;
|
|
7
9
|
type DeepReadonly<T> = T extends Date | RegExp | Function ? T : T extends readonly (infer E)[] ? readonly DeepReadonly<E>[] : T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]>; } : T;
|
|
8
10
|
type output<T> = T extends {
|
|
@@ -37,4 +39,4 @@ type JsonCompatible<T> = T extends string | number | boolean | null | undefined
|
|
|
37
39
|
toJSON: () => unknown;
|
|
38
40
|
} ? never : { [K in keyof T]: JsonCompatible<T[K]>; } : never;
|
|
39
41
|
//#endregion
|
|
40
|
-
export { DeepReadonly, DeepWritable, InferFieldsOutput, JsonCompatible, JsonValue, NullableToOptional, Prettify, TypeLevelError, output };
|
|
42
|
+
export { DeepReadonly, DeepWritable, InferFieldsOutput, IsUnion, JsonCompatible, JsonValue, NullableToOptional, Prettify, TypeLevelError, UnionToIntersection, output };
|
package/dist/vitest/index.d.mts
CHANGED
|
@@ -10,7 +10,7 @@ import { mockWorkflow } from "./mocks/workflow.mjs";
|
|
|
10
10
|
import "./mock.mjs";
|
|
11
11
|
import { RunWorkflowLocallyOptions, runWorkflowLocally } from "./workflow-local.mjs";
|
|
12
12
|
import { ExecutedQuery, KyselyMock, createKyselyMock } from "./mock-kysely.mjs";
|
|
13
|
-
import { PGliteClient, createKyselyPGlite } from "./pglite-kysely.mjs";
|
|
13
|
+
import { PGliteClient, Unmigrated, createKyselyPGlite } from "./pglite-kysely.mjs";
|
|
14
14
|
import { Plugin } from "vitest/config";
|
|
15
15
|
//#region src/vitest/index.d.ts
|
|
16
16
|
/**
|
|
@@ -72,4 +72,4 @@ declare function tailorRuntime(options?: {
|
|
|
72
72
|
config?: string;
|
|
73
73
|
}): Plugin[];
|
|
74
74
|
//#endregion
|
|
75
|
-
export { type ExecutedQuery, type KyselyMock, type MockAigatewayOptions, type MockAuthconnectionOptions, type MockFileOptions, type MockIconvOptions, type MockIdpOptions, type MockLoggerOptions, type MockSecretmanagerOptions, type MockTailordbOptions, type PGliteClient, type QueryBehavior, type QueryMatch, type QueryMatcher, type RunWorkflowLocallyOptions, createKyselyMock, createKyselyPGlite, mockAigateway, mockAuthconnection, mockFile, mockIconv, mockIdp, mockLogger, mockSecretmanager, mockTailordb, mockWorkflow, runWorkflowLocally, tailorRuntime };
|
|
75
|
+
export { type ExecutedQuery, type KyselyMock, type MockAigatewayOptions, type MockAuthconnectionOptions, type MockFileOptions, type MockIconvOptions, type MockIdpOptions, type MockLoggerOptions, type MockSecretmanagerOptions, type MockTailordbOptions, type PGliteClient, type QueryBehavior, type QueryMatch, type QueryMatcher, type RunWorkflowLocallyOptions, type Unmigrated, createKyselyMock, createKyselyPGlite, mockAigateway, mockAuthconnection, mockFile, mockIconv, mockIdp, mockLogger, mockSecretmanager, mockTailordb, mockWorkflow, runWorkflowLocally, tailorRuntime };
|