@lakeql/cli 0.2.0 → 0.2.2

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.
Files changed (2) hide show
  1. package/dist/cli.mjs +6 -6
  2. package/package.json +5 -5
package/dist/cli.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{Command as e,Option as t}from"@commander-js/extra-typings";import{readPackage as n}from"read-pkg";import{existsSync as r,readFileSync as i}from"node:fs";import{mkdir as a,readFile as o,rm as s,writeFile as c}from"node:fs/promises";import l from"node:path";import{createEnv as u}from"@t3-oss/env-core";import d from"dotenv";import{enum as f,number as p,string as m}from"zod/v4";import{generateCode as h}from"@lakeql/file-generator";import{generateConfig as ee}from"@lakeql/file-generator/config";import{generateInterface as te}from"@lakeql/file-generator/interface";import{generateQuerySchema as ne}from"@lakeql/file-generator/query-schema";import{generateModel as re}from"@lakeql/schema-generator/graphql-schema";import{generateJsonSchemaFromFields as ie}from"@lakeql/schema-generator/json-schema";import{generateConfigReqistry as g}from"@lakeql/file-generator/config-registry";import{globby as _}from"globby";import{camelCase as v,upperFirst as y}from"lodash-es";import b from"typescript";import{endpointDefinitionSchema as x,findDuplicateFieldNames as ae}from"@lakeql/schema-generator/endpoint-schema";import{TrinoClient as S}from"@lakeql/trino-client";import{multiselect as oe,question as se,select as C,validators as ce}from"@topcli/prompts";import{ClimtTable as w}from"climt";import{parseColumns as T}from"@lakeql/column-parser";import{error as E}from"@lakeql/logger/console";import{convertTrinoResponse as le}from"@lakeql/response-transformer";import D from"kleur";function O(e,t=0){let n=[],r=` `.repeat(t+1);for(let i of e)if(i.type===`Object`)n.push(`${r}${i.name}: Object`),i.fields&&n.push(O(i.fields,t+1));else if(i.type===`Array`){let e=i.items?.type??`Unknown`;n.push(`${r}${i.name}: Array<${e}>`),i.items?.type===`Object`&&i.items.fields&&n.push(O(i.items.fields,t+1))}else n.push(`${r}${i.name}: ${i.type}`);return n.filter(e=>e.length>0).join(`
3
- `)}function k(){return process.env.INIT_CWD??process.cwd()}const A=`lakeql.config.json`,ue={sourcePath:`.`};function de(){let e=l.join(k(),A);if(!r(e))return ue;let t=i(e,`utf-8`),n=JSON.parse(t);return{...ue,...n}}function j(e){let t=de(),n=k(),r=e??t.sourcePath;return l.isAbsolute(r)?r:l.resolve(n,r)}d.config({path:`../../.env`});const M=u({runtimeEnv:process.env,server:{HIVE_CATALOG:m().min(1),HIVE_HOST:m(),HIVE_PASSWORD:m().min(1),HIVE_PORT:m().transform(e=>Number.parseInt(e,10)).pipe(p()),HIVE_SOURCE:m().optional(),HIVE_USERNAME:m().min(1),LOG_LEVEL:f([`info`,`warn`,`error`,`debug`]).default(`warn`)}}),N=new t(`--catalog <catalog>`,`catalog to use`).default(M.HIVE_CATALOG,`configured catalog in the .env file`),P=new t(`--schema <schema>`,`schema to use`),fe=new t(`--table <table>`,`table to use`),pe=new t(`--type <type>`,`Show tables or views`),F=new t(`--source-path <path>`,"Base path for generated code (resolved from the command invocation directory). Files are created in `schemas/generated` inside this path.").default(k(),`command invocation directory`),me=new t(`--skip-registry`,`Skip config registry generation`).default(!1);function he(){return new e(`create-registry`).description("Generates the config registry to ensure the type-safety while using `createPermission`").addOption(F).action(async({sourcePath:e})=>{await I(e!==process.env.INIT_CWD&&e!==process.cwd()?e:void 0)})}async function I(e){let t=j(e),n=await h({fileName:`config-registry.ts`,nodes:g({configPaths:(await _(`schemas/**/config.ts`,{cwd:t,onlyFiles:!0})).map(e=>{let t=l.parse(e);return l.join(t.dir,t.name)})})});r(l.join(t,`config-registry.ts`))&&await s(l.join(t,`config-registry.ts`),{force:!0,recursive:!0}),await c(l.join(t,`config-registry.ts`),n.text)}function ge(e,t){return{baseClassName:`${y(v(e))}_${y(v(t))}`,queryName:`${v(e)}${y(v(t))}`,mutationName:`create${v(e)}${y(v(t))}`}}const{factory:L}=b;function R(e){return L.createIdentifier(e)}function z(e){return R(e)}function B(e){return L.createStringLiteral(e)}function V(e,t){return L.createPropertyAssignment(R(e),t)}function H(e,t=!0){return L.createObjectLiteralExpression(e,t)}function U(e){return e?L.createTrue():L.createFalse()}function W(e){return L.createParameterDeclaration(void 0,void 0,R(e))}function G(e,t,n){return L.createArrowFunction(n?.async?[L.createToken(b.SyntaxKind.AsyncKeyword)]:void 0,void 0,e.map(e=>typeof e==`string`?W(e):e),void 0,L.createToken(b.SyntaxKind.EqualsGreaterThanToken),t)}function _e(e){return L.createParenthesizedExpression(e)}function K(e,t=!0){return G([`t`],_e(H(e,t)))}function q(e,t){return L.createPropertyAccessExpression(typeof e==`string`?R(e):e,R(t))}function ve(e,t=[],n){return L.createCallExpression(e,n,t)}function J(e,t,n=[],r){return ve(q(e,t),n,r)}function Y(e,t=[],n){return J(`builder`,e,t,n)}function ye(e,t){return L.createVariableStatement(void 0,L.createVariableDeclarationList([L.createVariableDeclaration(R(e),void 0,void 0,t)],b.NodeFlags.Const))}function X(e,t,n){return L.createImportDeclaration(void 0,L.createImportClause(n?.typeOnly??!1,void 0,L.createNamedImports(t.map(e=>L.createImportSpecifier(!1,void 0,R(e))))),B(e))}function be(e,t,n){return L.createImportDeclaration(void 0,L.createImportClause(n?.typeOnly??!1,R(t),void 0),B(e))}function xe({models:e,mutationName:t,mutationConfig:n,hasValidations:r,fieldDefinitions:i}){if(n===!1)return[];let a=Object.values(e).find(e=>e.root);if(!a)return[];let o=Se(i),s=Object.values(e).filter(e=>!e.root);return n&&typeof n==`object`?[...Ce(r),...s.map(t=>Z(t,e,o)),Z(a,e,o),Oe(t,a,n,r)]:[we(),...s.map(t=>Z(t,e,o)),Z(a,e,o),ke(t,a)]}function Se(e){let t=new Map;if(!e)return t;for(let n of e){let e=n.options?.required===!0;t.set(n.name,e)}return t}function Ce(e){let t=[X(`@lakeql/adapters`,[`executeWritePipeline`]),X(`@lakeql/trino-client`,[`TrinoClient`]),X(`@lakeql/api/builder`,[`builder`]),X(`~/env`,[`env`]),X(`./config`,[`hiveConfig`]),be(`./json-schema.json`,`jsonSchema`)];return e&&t.push(X(`./validations`,[`validationSchema`])),t}function we(){return X(`@lakeql/api/builder`,[`builder`])}function Z(e,t,n){let r=`${e.modelName}Input`,i=Object.values(e.fields).map(e=>Te(e,t,n));return ye(r,Y(`inputType`,[B(r),H([V(`fields`,K(i))])]))}function Te(e,t,n){let r=V(`required`,U(n.get(e.name)??!0));if(e.isArray){let t=e.graphqlType.replace(/^\[/u,``).replace(/\]$/u,``),n=De(t);if(n)return V(e.name,J(`t`,n,[H([r],!1)]));let i=`${t}Input`;return V(e.name,J(`t`,`field`,[H([V(`type`,b.factory.createArrayLiteralExpression([z(i)])),r],!1)]))}let i=Ee(e.graphqlType);if(i)return V(e.name,J(`t`,i,[H([r],!1)]));if(Object.keys(t).includes(e.graphqlType)){let t=`${e.graphqlType}Input`;return V(e.name,J(`t`,`field`,[H([V(`type`,z(t)),r],!1)]))}return V(e.name,J(`t`,`string`,[H([r],!1)]))}function Ee(e){switch(e){case`String`:return`string`;case`Int`:return`int`;case`Float`:return`float`;case`Boolean`:return`boolean`;default:return}}function De(e){switch(e){case`String`:return`stringList`;case`Int`:return`intList`;case`Float`:return`floatList`;case`Boolean`:return`booleanList`;default:return}}function Oe(e,t,n,r){let i=`${t.modelName}Input`,a=[];r&&a.push(b.factory.createExpressionStatement(J(`validationSchema`,`parse`,[z(`input`)]))),a.push(b.factory.createVariableStatement(void 0,b.factory.createVariableDeclarationList([b.factory.createVariableDeclaration(z(`trinoClient`),void 0,void 0,b.factory.createNewExpression(z(`TrinoClient`),void 0,[H([V(`host`,q(`env`,`HIVE_HOST`)),V(`port`,q(`env`,`HIVE_PORT`)),V(`auth`,H([V(`type`,B(`basic`)),V(`username`,q(`env`,`HIVE_USERNAME`)),V(`password`,q(`env`,`HIVE_PASSWORD`))],!1)),V(`catalog`,q(`env`,`HIVE_CATALOG`)),V(`source`,q(`env`,`HIVE_SOURCE`))])]))],b.NodeFlags.Const)));let o=b.factory.createAwaitExpression(ve(z(`executeWritePipeline`),[H([V(`records`,z(`input`)),V(`jsonSchema`,b.factory.createAsExpression(z(`jsonSchema`),b.factory.createKeywordTypeNode(b.SyntaxKind.AnyKeyword))),V(`config`,H([V(`loadStrategy`,B(n.loadStrategy)),V(`basePath`,B(n.basePath)),V(`s3`,H([V(`bucket`,q(`env`,`S3_BUCKET`)),V(`region`,q(`env`,`S3_REGION`)),V(`endpoint`,q(`env`,`S3_ENDPOINT`)),V(`credentials`,H([V(`accessKeyId`,q(`env`,`S3_ACCESS_KEY_ID`)),V(`secretAccessKey`,q(`env`,`S3_SECRET_ACCESS_KEY`))],!1))])),V(`table`,H([V(`catalog`,q(`hiveConfig`,`catalog`)),V(`schema`,q(`hiveConfig`,`schema`)),V(`tableName`,q(`hiveConfig`,`tableName`))],!1)),V(`trinoClient`,z(`trinoClient`))]))])]));a.push(b.factory.createExpressionStatement(o)),a.push(b.factory.createReturnStatement(b.factory.createTrue()));let s=b.factory.createBlock(a,!0),c=G([W(`_root`),b.factory.createParameterDeclaration(void 0,void 0,b.factory.createObjectBindingPattern([b.factory.createBindingElement(void 0,void 0,b.factory.createIdentifier(`input`))]))],s,{async:!0}),l=V(e,J(`t`,`boolean`,[H([V(`args`,H([V(`input`,J(`t`,`arg`,[H([V(`type`,z(i)),V(`required`,U(!0))],!1)]))],!1)),V(`resolve`,c)])]));return b.factory.createExpressionStatement(Y(`mutationFields`,[K([l])]))}function ke(e,t){let n=`${t.modelName}Input`,r=b.factory.createBlock([b.addSyntheticLeadingComment(b.factory.createReturnStatement(b.factory.createTrue()),b.SyntaxKind.SingleLineCommentTrivia,` TODO: Implement write logic here`,!0)],!0),i=G([W(`_root`),b.factory.createParameterDeclaration(void 0,void 0,b.factory.createObjectBindingPattern([b.factory.createBindingElement(void 0,void 0,b.factory.createIdentifier(`input`))]))],r,{async:!0}),a=V(e,J(`t`,`boolean`,[H([V(`args`,H([V(`input`,J(`t`,`arg`,[H([V(`type`,z(n)),V(`required`,U(!0))],!1)]))],!1)),V(`resolve`,i)])]));return b.factory.createExpressionStatement(Y(`mutationFields`,[K([a])]))}function Q(e){if(typeof e!=`object`||!e)return e;if(Array.isArray(e))return e.map(Q);let t={},n=Object.keys(e).toSorted();for(let r of n)t[r]=Q(e[r]);return t}function Ae(e){let t=Q(e);return`${JSON.stringify(t,null,2).replaceAll(`\r
2
+ import{Command as e,Option as t}from"@commander-js/extra-typings";import{readPackage as n}from"read-pkg";import{existsSync as r,readFileSync as i}from"node:fs";import{mkdir as a,readFile as o,rm as s,writeFile as c}from"node:fs/promises";import l from"node:path";import{generateCode as u}from"@lakeql/file-generator";import{generateConfig as d}from"@lakeql/file-generator/config";import{generateInterface as f}from"@lakeql/file-generator/interface";import{generateQuerySchema as ee}from"@lakeql/file-generator/query-schema";import{generateModel as te}from"@lakeql/schema-generator/graphql-schema";import{generateJsonSchemaFromFields as p}from"@lakeql/schema-generator/json-schema";import{generateConfigReqistry as ne}from"@lakeql/file-generator/config-registry";import{globby as m}from"globby";import{camelCase as h,upperFirst as g}from"lodash-es";import _ from"typescript";import{endpointDefinitionSchema as v,findDuplicateFieldNames as y}from"@lakeql/schema-generator/endpoint-schema";import{TrinoClient as b}from"@lakeql/trino-client";import{multiselect as x,question as S,select as C,validators as re}from"@topcli/prompts";import{ClimtTable as w}from"climt";import{createEnv as ie}from"@t3-oss/env-core";import ae from"dotenv";import{enum as oe,number as se,string as T}from"zod/v4";import{parseColumns as E}from"@lakeql/column-parser";import{error as D}from"@lakeql/logger/console";import{convertTrinoResponse as ce}from"@lakeql/response-transformer";import O from"kleur";function k(e,t=0){let n=[],r=` `.repeat(t+1);for(let i of e)if(i.type===`Object`)n.push(`${r}${i.name}: Object`),i.fields&&n.push(k(i.fields,t+1));else if(i.type===`Array`){let e=i.items?.type??`Unknown`;n.push(`${r}${i.name}: Array<${e}>`),i.items?.type===`Object`&&i.items.fields&&n.push(k(i.items.fields,t+1))}else n.push(`${r}${i.name}: ${i.type}`);return n.filter(e=>e.length>0).join(`
3
+ `)}function A(){return process.env.INIT_CWD??process.cwd()}const j=`lakeql.config.json`,le={sourcePath:`.`};function ue(){let e=l.join(A(),j);if(!r(e))return le;let t=i(e,`utf-8`),n=JSON.parse(t);return{...le,...n}}function M(e){let t=ue(),n=A(),r=e??t.sourcePath;return l.isAbsolute(r)?r:l.resolve(n,r)}const N=new t(`--catalog <catalog>`,`catalog to use`).env(`HIVE_CATALOG`),P=new t(`--schema <schema>`,`schema to use`),de=new t(`--table <table>`,`table to use`),fe=new t(`--type <type>`,`Show tables or views`),F=new t(`--source-path <path>`,"Base path for generated code (resolved from the command invocation directory). Files are created in `schemas/generated|custom` inside this path.").default(A(),`command invocation directory`),pe=new t(`--skip-registry`,`Skip config registry generation`).default(!1);function me(){return new e(`create-registry`).description("Generates the config registry to ensure the type-safety while using `createPermission`").addOption(F).action(async({sourcePath:e})=>{await he(e!==process.env.INIT_CWD&&e!==process.cwd()?e:void 0)})}async function he(e){let t=M(e),n=await u({fileName:`config-registry.ts`,nodes:ne({configPaths:(await m(`schemas/**/config.ts`,{cwd:t,onlyFiles:!0})).map(e=>{let t=l.parse(e);return l.join(t.dir,t.name)})})});r(l.join(t,`config-registry.ts`))&&await s(l.join(t,`config-registry.ts`),{force:!0,recursive:!0}),await c(l.join(t,`config-registry.ts`),n.text)}function ge(e,t){return{baseClassName:`${g(h(e))}_${g(h(t))}`,queryName:`${h(e)}${g(h(t))}`,mutationName:`create${h(e)}${g(h(t))}`}}const{factory:I}=_;function L(e){return I.createIdentifier(e)}function R(e){return L(e)}function z(e){return I.createStringLiteral(e)}function B(e,t){return I.createPropertyAssignment(L(e),t)}function V(e,t=!0){return I.createObjectLiteralExpression(e,t)}function H(e){return e?I.createTrue():I.createFalse()}function U(e){return I.createParameterDeclaration(void 0,void 0,L(e))}function W(e,t,n){return I.createArrowFunction(n?.async?[I.createToken(_.SyntaxKind.AsyncKeyword)]:void 0,void 0,e.map(e=>typeof e==`string`?U(e):e),void 0,I.createToken(_.SyntaxKind.EqualsGreaterThanToken),t)}function _e(e){return I.createParenthesizedExpression(e)}function G(e,t=!0){return W([`t`],_e(V(e,t)))}function K(e,t){return I.createPropertyAccessExpression(typeof e==`string`?L(e):e,L(t))}function ve(e,t=[],n){return I.createCallExpression(e,n,t)}function q(e,t,n=[],r){return ve(K(e,t),n,r)}function J(e,t=[],n){return q(`builder`,e,t,n)}function ye(e,t){return I.createVariableStatement(void 0,I.createVariableDeclarationList([I.createVariableDeclaration(L(e),void 0,void 0,t)],_.NodeFlags.Const))}function Y(e,t,n){return I.createImportDeclaration(void 0,I.createImportClause(n?.typeOnly??!1,void 0,I.createNamedImports(t.map(e=>I.createImportSpecifier(!1,void 0,L(e))))),z(e))}function be(e,t,n){return I.createImportDeclaration(void 0,I.createImportClause(n?.typeOnly??!1,L(t),void 0),z(e))}function xe({models:e,mutationName:t,mutationConfig:n,hasValidations:r,fieldDefinitions:i}){if(n===!1)return[];let a=Object.values(e).find(e=>e.root);if(!a)return[];let o=Se(i),s=Object.values(e).filter(e=>!e.root);return n&&typeof n==`object`?[...Ce(r),...s.map(t=>X(t,e,o)),X(a,e,o),Oe(t,a,n,r)]:[we(),...s.map(t=>X(t,e,o)),X(a,e,o),ke(t,a)]}function Se(e){let t=new Map;if(!e)return t;for(let n of e){let e=n.options?.required===!0;t.set(n.name,e)}return t}function Ce(e){let t=[Y(`@lakeql/adapters`,[`executeWritePipeline`]),Y(`@lakeql/trino-client`,[`TrinoClient`]),Y(`@lakeql/api/builder`,[`builder`]),Y(`~/env`,[`env`]),Y(`./config`,[`hiveConfig`]),be(`./json-schema.json`,`jsonSchema`)];return e&&t.push(Y(`./validations`,[`validationSchema`])),t}function we(){return Y(`@lakeql/api/builder`,[`builder`])}function X(e,t,n){let r=`${e.modelName}Input`,i=Object.values(e.fields).map(e=>Te(e,t,n));return ye(r,J(`inputType`,[z(r),V([B(`fields`,G(i))])]))}function Te(e,t,n){let r=B(`required`,H(n.get(e.name)??!0));if(e.isArray){let t=e.graphqlType.replace(/^\[/u,``).replace(/\]$/u,``),n=De(t);if(n)return B(e.name,q(`t`,n,[V([r],!1)]));let i=`${t}Input`;return B(e.name,q(`t`,`field`,[V([B(`type`,_.factory.createArrayLiteralExpression([R(i)])),r],!1)]))}let i=Ee(e.graphqlType);if(i)return B(e.name,q(`t`,i,[V([r],!1)]));if(Object.keys(t).includes(e.graphqlType)){let t=`${e.graphqlType}Input`;return B(e.name,q(`t`,`field`,[V([B(`type`,R(t)),r],!1)]))}return B(e.name,q(`t`,`string`,[V([r],!1)]))}function Ee(e){switch(e){case`String`:return`string`;case`Int`:return`int`;case`Float`:return`float`;case`Boolean`:return`boolean`;default:return}}function De(e){switch(e){case`String`:return`stringList`;case`Int`:return`intList`;case`Float`:return`floatList`;case`Boolean`:return`booleanList`;default:return}}function Oe(e,t,n,r){let i=`${t.modelName}Input`,a=[];r&&a.push(_.factory.createExpressionStatement(q(`validationSchema`,`parse`,[R(`input`)]))),a.push(_.factory.createVariableStatement(void 0,_.factory.createVariableDeclarationList([_.factory.createVariableDeclaration(R(`trinoClient`),void 0,void 0,_.factory.createNewExpression(R(`TrinoClient`),void 0,[V([B(`host`,K(`env`,`HIVE_HOST`)),B(`port`,K(`env`,`HIVE_PORT`)),B(`auth`,V([B(`type`,z(`basic`)),B(`username`,K(`env`,`HIVE_USERNAME`)),B(`password`,K(`env`,`HIVE_PASSWORD`))],!1)),B(`catalog`,K(`env`,`HIVE_CATALOG`)),B(`source`,K(`env`,`HIVE_SOURCE`))])]))],_.NodeFlags.Const)));let o=_.factory.createAwaitExpression(ve(R(`executeWritePipeline`),[V([B(`records`,R(`input`)),B(`jsonSchema`,_.factory.createAsExpression(R(`jsonSchema`),_.factory.createKeywordTypeNode(_.SyntaxKind.AnyKeyword))),B(`config`,V([B(`loadStrategy`,z(n.loadStrategy)),B(`basePath`,z(n.basePath)),B(`s3`,V([B(`bucket`,K(`env`,`S3_BUCKET`)),B(`region`,K(`env`,`S3_REGION`)),B(`endpoint`,K(`env`,`S3_ENDPOINT`)),B(`credentials`,V([B(`accessKeyId`,K(`env`,`S3_ACCESS_KEY_ID`)),B(`secretAccessKey`,K(`env`,`S3_SECRET_ACCESS_KEY`))],!1))])),B(`table`,V([B(`catalog`,K(`hiveConfig`,`catalog`)),B(`schema`,K(`hiveConfig`,`schema`)),B(`tableName`,K(`hiveConfig`,`tableName`))],!1)),B(`trinoClient`,R(`trinoClient`))]))])]));a.push(_.factory.createExpressionStatement(o)),a.push(_.factory.createReturnStatement(_.factory.createTrue()));let s=_.factory.createBlock(a,!0),c=W([U(`_root`),_.factory.createParameterDeclaration(void 0,void 0,_.factory.createObjectBindingPattern([_.factory.createBindingElement(void 0,void 0,_.factory.createIdentifier(`input`))]))],s,{async:!0}),l=B(e,q(`t`,`boolean`,[V([B(`args`,V([B(`input`,q(`t`,`arg`,[V([B(`type`,R(i)),B(`required`,H(!0))],!1)]))],!1)),B(`resolve`,c)])]));return _.factory.createExpressionStatement(J(`mutationFields`,[G([l])]))}function ke(e,t){let n=`${t.modelName}Input`,r=_.factory.createBlock([_.addSyntheticLeadingComment(_.factory.createReturnStatement(_.factory.createTrue()),_.SyntaxKind.SingleLineCommentTrivia,` TODO: Implement write logic here`,!0)],!0),i=W([U(`_root`),_.factory.createParameterDeclaration(void 0,void 0,_.factory.createObjectBindingPattern([_.factory.createBindingElement(void 0,void 0,_.factory.createIdentifier(`input`))]))],r,{async:!0}),a=B(e,q(`t`,`boolean`,[V([B(`args`,V([B(`input`,q(`t`,`arg`,[V([B(`type`,R(n)),B(`required`,H(!0))],!1)]))],!1)),B(`resolve`,i)])]));return _.factory.createExpressionStatement(J(`mutationFields`,[G([a])]))}function Z(e){if(typeof e!=`object`||!e)return e;if(Array.isArray(e))return e.map(Z);let t={},n=Object.keys(e).toSorted();for(let r of n)t[r]=Z(e[r]);return t}function Ae(e){let t=Z(e);return`${JSON.stringify(t,null,2).replaceAll(`\r
4
4
  `,`
5
- `)}\n`}async function je(e){let{definition:t,outputDir:n,skipRegistry:i,sourcePathOverride:o}=e,{catalog:u,schema:d,tableName:f,fields:p}=t,{baseClassName:m,queryName:g,mutationName:_}=ge(d,f),v=ie(p),y=re({isRoot:!0,models:{},name:m,source:v}),b=Object.values(y).find(e=>e.root===!0),x=b?.fields?Object.values(b.fields).filter(e=>e.filter===!0).map(e=>({name:e.name,type:e.graphqlType})):[],ae=[...new Set(x.map(e=>e.type))],S=[...new Set(Object.values(y).filter(e=>e.transformFields.length>0).flatMap(e=>e.transformFields))],oe=[...new Set(Object.values(y).filter(e=>e.dateTimeFields.length>0).flatMap(e=>e.dateTimeFields))],se=await h({fileName:`config.ts`,nodes:ee({catalog:u,queryName:g,schema:d,tableName:f,mutationName:[_]})}),C=await h({fileName:`interface.ts`,nodes:te(y)}),ce=await h({fileName:`query-schema.ts`,nodes:ne({dateTimeFields:oe,filterFields:x,filterTypes:ae,models:y,queryName:g,transformFields:S})}),w=p.some(e=>e.options?.validations&&e.options.validations.length>0),T=xe({models:y,mutationName:_,mutationConfig:t.mutation,hasValidations:w,fieldDefinitions:p}),E=``;T.length>0&&(E=(await h({fileName:`mutation-schema.ts`,nodes:T})).text);let le=Ae(v),D=Ae(t),O=[{fileName:`config.ts`,content:se.text},{fileName:`interface.ts`,content:C.text},{fileName:`query-schema.ts`,content:ce.text},{fileName:`json-schema.json`,content:le},{fileName:`endpoint.json`,content:D}];E&&O.push({fileName:`mutation-schema.ts`,content:E}),r(n)&&await s(n,{force:!0,recursive:!0}),await a(n,{recursive:!0});for(let e of O)await c(l.join(n,e.fileName),e.content);return i||await I(o),{files:O,outputDir:n}}function Me(){return new e(`create-endpoint`).description(`Create a custom endpoint from a JSON definition file`).addOption(new t(`--from-file <path>`,`Path to a JSON definition file conforming to the Endpoint_Definition_Format`).makeOptionMandatory(!0)).addOption(new t(`--no-interactive`,`Skip all prompts and generate directly (always non-interactive)`)).addOption(F).addOption(me).action(async e=>{let{fromFile:t,sourcePath:n,skipRegistry:i}=e,a=l.isAbsolute(t)?t:l.resolve(process.cwd(),t);r(a)||(console.error(`Error: File not found: ${a}`),process.exit(1));let s;try{s=await o(a,`utf-8`)}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`Error: Cannot read file: ${a}: ${t}`),process.exit(1)}let c;try{c=JSON.parse(s)}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`Error: Invalid JSON in ${a}: ${t}`),process.exit(1)}let u=x.safeParse(c);if(!u.success){let e=u.error.issues.map(e=>` - ${e.path.length>0?e.path.join(`.`):`root`}: ${e.message}`).join(`
6
- `);console.error(`Error: Validation failed for ${a}:\n${e}`),process.exit(1)}let d=u.data,f=ae(d.fields);if(f.length>0){let e=f.map(e=>{let t=e.path.length>0?e.path.join(`.`):`root`;return` - Duplicate field "${e.name}" at level: ${t}`}).join(`
5
+ `)}\n`}async function je(e){let{definition:t,outputDir:n,skipRegistry:i,sourcePathOverride:o}=e,{catalog:ne,schema:m,tableName:h,fields:g}=t,{baseClassName:_,queryName:v,mutationName:y}=ge(m,h),b=p(g),x=te({isRoot:!0,models:{},name:_,source:b}),S=Object.values(x).find(e=>e.root===!0),C=S?.fields?Object.values(S.fields).filter(e=>e.filter===!0).map(e=>({name:e.name,type:e.graphqlType})):[],re=[...new Set(C.map(e=>e.type))],w=[...new Set(Object.values(x).filter(e=>e.transformFields.length>0).flatMap(e=>e.transformFields))],ie=[...new Set(Object.values(x).filter(e=>e.dateTimeFields.length>0).flatMap(e=>e.dateTimeFields))],ae=await u({fileName:`config.ts`,nodes:d({catalog:ne,queryName:v,schema:m,tableName:h,mutationName:[y]})}),oe=await u({fileName:`interface.ts`,nodes:f(x)}),se=await u({fileName:`query-schema.ts`,nodes:ee({dateTimeFields:ie,filterFields:C,filterTypes:re,models:x,queryName:v,transformFields:w})}),T=g.some(e=>e.options?.validations&&e.options.validations.length>0),E=xe({models:x,mutationName:y,mutationConfig:t.mutation,hasValidations:T,fieldDefinitions:g}),D=``;E.length>0&&(D=(await u({fileName:`mutation-schema.ts`,nodes:E})).text);let ce=Ae(b),O=Ae(t),k=[{fileName:`config.ts`,content:ae.text},{fileName:`interface.ts`,content:oe.text},{fileName:`query-schema.ts`,content:se.text},{fileName:`json-schema.json`,content:ce},{fileName:`endpoint.json`,content:O}];D&&k.push({fileName:`mutation-schema.ts`,content:D}),r(n)&&await s(n,{force:!0,recursive:!0}),await a(n,{recursive:!0});for(let e of k)await c(l.join(n,e.fileName),e.content);return i||await he(o),{files:k,outputDir:n}}function Me(){return new e(`create-endpoint`).description(`Create a custom endpoint from a JSON definition file`).addOption(new t(`--from-file <path>`,`Path to a JSON definition file conforming to the Endpoint_Definition_Format`).makeOptionMandatory(!0)).addOption(F).addOption(pe).action(async e=>{let{fromFile:t,sourcePath:n,skipRegistry:i}=e,a=l.isAbsolute(t)?t:l.resolve(process.cwd(),t);r(a)||(console.error(`Error: File not found: ${a}`),process.exit(1));let s;try{s=await o(a,`utf-8`)}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`Error: Cannot read file: ${a}: ${t}`),process.exit(1)}let c;try{c=JSON.parse(s)}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`Error: Invalid JSON in ${a}: ${t}`),process.exit(1)}let u=v.safeParse(c);if(!u.success){let e=u.error.issues.map(e=>` - ${e.path.length>0?e.path.join(`.`):`root`}: ${e.message}`).join(`
6
+ `);console.error(`Error: Validation failed for ${a}:\n${e}`),process.exit(1)}let d=u.data,f=y(d.fields);if(f.length>0){let e=f.map(e=>{let t=e.path.length>0?e.path.join(`.`):`root`;return` - Duplicate field "${e.name}" at level: ${t}`}).join(`
7
7
  `);console.error(`Error: Validation failed for ${a}:\n${e}`),process.exit(1)}console.log(`
8
- Loaded definition summary:`),console.log(` tableName: ${d.tableName}`),console.log(` catalog: ${d.catalog}`),console.log(` schema: ${d.schema}`);let p=d.mutation?d.mutation.loadStrategy:`disabled`;console.log(` mutation: ${p}`),console.log(`
9
- Fields:`),console.log(O(d.fields)),console.log(``);let m=j(n===process.cwd()?void 0:n),h=l.join(m,`schemas/custom`,d.catalog,d.schema,d.tableName);await je({definition:d,outputDir:h,skipRegistry:i,sourcePathOverride:n===process.cwd()?void 0:n}),console.log(`Endpoint generated successfully at: ${h}`)})}function Ne(){let t=new e(`list-columns`);return t.description(`Lists the columns for the specified table`).addOption(N).addOption(P.makeOptionMandatory()).addOption(fe.makeOptionMandatory()).action(async({catalog:e,schema:t,table:n})=>{let r=new S({auth:{password:M.HIVE_PASSWORD,type:`basic`,username:M.HIVE_USERNAME},catalog:e,host:M.HIVE_HOST,port:M.HIVE_PORT}),i=t;if(i===void 0){let t=await r.schemas({catalog:e});i=await C(`Choose a schema from the ${e} catalog`,{autocomplete:!0,choices:t})}let a=n;if(a===void 0){let t=await r.tables({catalog:e,schema:i});a=await C(`Choose a table from "${e}.${i}"`,{autocomplete:!0,choices:t})}let o=(await r.columns({catalog:e,schema:i,table:a})).map(([e,t,n,r])=>({description:r,extra:n,name:e,type:t})),s=new w;s.column(`Column Name`,`name`),s.column(`Type`,`type`),s.column(`Extra`,`extra`),s.column(`Description`,`description`),s.render(o)}),t}function Pe(){let t=new e(`list-schemas`);return t.description(`Lists the available schemas for the configured catalog`).addOption(N).action(async({catalog:e})=>{let t=await new S({auth:{password:M.HIVE_PASSWORD,type:`basic`,username:M.HIVE_USERNAME},catalog:e,host:M.HIVE_HOST,port:M.HIVE_PORT}).schemas({catalog:e}),n=new w;n.column(`Schema Name`,`s`),n.render(t.map(e=>({s:e})))}),t}function Fe(){let t=new e(`list-tables`);return t.description(`Lists the available tables for the configured catalog/schema`).addOption(N).addOption(P).action(async({catalog:e,schema:t})=>{let n=new S({auth:{password:M.HIVE_PASSWORD,type:`basic`,username:M.HIVE_USERNAME},catalog:e,host:M.HIVE_HOST,port:M.HIVE_PORT}),r=t;if(r===void 0){let t=await n.schemas({catalog:e});r=await C(`Choose a schema from the ${e} catalog`,{autocomplete:!0,choices:t})}let i=await n.tables({catalog:e,schema:r}),a=new w;a.column(`Table Name`,`t`),a.render(i.map(e=>({t:e})))}),t}function Ie(){let t=new e(`list-views`);return t.description(`Lists the available views for the configured catalog/schema`).addOption(N).addOption(P).action(async({catalog:e,schema:t})=>{let n=new S({auth:{password:M.HIVE_PASSWORD,type:`basic`,username:M.HIVE_USERNAME},catalog:e,host:M.HIVE_HOST,port:M.HIVE_PORT}),r=t;if(r===void 0){let t=await n.schemas({catalog:e});r=await C(`Choose a schema from the ${e} catalog`,{choices:t})}let i=await n.views({catalog:e,schema:r}),a=new w;a.column(`View Name`,`v`),a.render(i.map(e=>({v:e})))}),t}function Le(e){switch(e.replaceAll(/[^a-zA-Z]/gu,``)){case`varchar`:return`String`;case`decimal`:case`double`:case`float`:return`Float`;case`integer`:case`bigint`:return`Integer`;case`boolean`:return`Boolean`;case`timestamp`:return`DateTime`;case`date`:return`Date`;default:return`String`}}function Re(e,t){return typeof t==`string`?{name:e,type:Le(t)}:Array.isArray(t)?{name:e,type:`Array`,items:ze(t)}:typeof t==`object`&&t?{name:e,type:`Object`,fields:$(t)}:{name:e,type:`String`}}function ze(e){if(e.length===0)return{type:`String`};let[t]=e;return typeof t==`string`?{type:Le(t)}:typeof t==`object`&&t&&!Array.isArray(t)?{type:`Object`,fields:$(t)}:{type:`String`}}function $(e){let t=[];for(let[n,r]of Object.entries(e))t.push(Re(n,r));return t}function Be(e){let{tableName:t,catalog:n,schema:r,parsedColumns:i}=e;return{version:`1.0`,tableName:t,catalog:n,schema:r,fields:$(i),mutation:!1}}function Ve(){let t=new e(`pull`),n=t.description(`Interactive query endpoint generation based on a remote table`).addOption(N).addOption(pe).addOption(P.makeOptionMandatory(!1)).addOption(fe.makeOptionMandatory(!1).default([]).argParser((e,t)=>[...t,e])).addOption(me).addOption(F);return n.action(async e=>{let{catalog:n,skipRegistry:r,sourcePath:i}=e,{schema:a,table:o,type:s}=e,c=i===(process.env.INIT_CWD??process.cwd())?void 0:i,u=j(c),d=new S({auth:{password:M.HIVE_PASSWORD,type:`basic`,username:M.HIVE_USERNAME},catalog:n,host:M.HIVE_HOST,port:M.HIVE_PORT});if(!a){let e=await d.schemas({catalog:n});a=await C(`Choose a schema from the ${n} catalog`,{autocomplete:!0,choices:e})}if(o.length===0&&(s??=await C(`What do you want to see from ${n}/${a}`,{choices:[{label:`Show tables`,value:`tables`},{label:`Show views`,value:`views`}]})),o.length===0){let e=[];e=s===`views`?await d.views({catalog:n,schema:a}):await d.tables({catalog:n,schema:a}),e.length===0&&t.error(E(`There are no tables in schema '${n}.${a}'.`),{exitCode:0}),o=await oe(`Choose the tables to pull`,{autocomplete:!0,choices:e,validators:[ce.required()]})}for(let e of o){let t=T((await d.columns({catalog:n,schema:a,table:e})).map(e=>le({keys:[`name`,`type`,`extra`,`description`],values:e})));await je({definition:Be({tableName:e,catalog:n,schema:a,parsedColumns:t}),outputDir:l.join(u,`schemas/generated`,n,a,e),skipRegistry:r,sourcePathOverride:c})}}),n}function He(){return new e(`init`).description(`Initialize a lakeql.config.json configuration file`).action(async()=>{let e=k(),t=l.join(e,A);if(r(t)&&await C(`lakeql.config.json already exists. Overwrite?`,{choices:[{label:`Yes`,value:`yes`},{label:`No`,value:`no`}]})===`no`){console.log(D.yellow(`Aborted.`));return}let n=r(l.join(e,`src`)),i;if(n)i=`src`,console.log(D.cyan(`Detected src/ directory — generated code will be placed in src/`));else{let e=await C(`Where should generated code be placed?`,{choices:[{label:`./ (project root)`,value:`.`},{label:`Custom path`,value:`__custom__`}]});i=e,e===`__custom__`&&(i=await se(`Enter the source path (relative to project root):`,{defaultValue:`.`}))}await c(t,`${JSON.stringify({sourcePath:i},null,2)}\n`),console.log(D.green(`Created ${A} at ${t}`))})}async function Ue(){let t=await n(),r=new e;r.configureHelp({sortSubcommands:!0}),r.name(`lakeql-cli`).description(`LakeQL CLI`).version(t.version).addCommand(Pe()).addCommand(Fe()).addCommand(Ie()).addCommand(Ne()).addCommand(Ve()).addCommand(Me()).addCommand(he()).addCommand(He()),await r.parseAsync()}Ue().catch(()=>{process.exit(1)});export{};
8
+ Loaded definition summary:`),console.log(` tableName: ${d.tableName}`),console.log(` catalog: ${d.catalog}`),console.log(` schema: ${d.schema}`);let ee=d.mutation?d.mutation.loadStrategy:`disabled`;console.log(` mutation: ${ee}`),console.log(`
9
+ Fields:`),console.log(k(d.fields)),console.log(``);let te=M(n===process.cwd()?void 0:n),p=l.join(te,`schemas/custom`,d.catalog,d.schema,d.tableName);await je({definition:d,outputDir:p,skipRegistry:i,sourcePathOverride:n===process.cwd()?void 0:n}),console.log(`Endpoint generated successfully at: ${p}`)})}let Ne;function Pe(){return ae.config({path:`../../.env`}),ie({runtimeEnv:process.env,server:{HIVE_CATALOG:T().min(1),HIVE_HOST:T(),HIVE_PASSWORD:T().min(1),HIVE_PORT:T().transform(e=>Number.parseInt(e,10)).pipe(se()),HIVE_SOURCE:T().optional(),HIVE_USERNAME:T().min(1),LOG_LEVEL:oe([`info`,`warn`,`error`,`debug`]).default(`warn`)}})}function Q(){return Ne||=Pe(),Ne}function Fe(){let t=new e(`list-columns`);return t.description(`Lists the columns for the specified table`).addOption(N).addOption(P.makeOptionMandatory()).addOption(de.makeOptionMandatory()).action(async({catalog:e,schema:t,table:n})=>{let r=Q(),i=e??r.HIVE_CATALOG,a=new b({auth:{password:r.HIVE_PASSWORD,type:`basic`,username:r.HIVE_USERNAME},catalog:i,host:r.HIVE_HOST,port:r.HIVE_PORT}),o=t;if(o===void 0){let e=await a.schemas({catalog:i});o=await C(`Choose a schema from the ${i} catalog`,{autocomplete:!0,choices:e})}let s=n;if(s===void 0){let e=await a.tables({catalog:i,schema:o});s=await C(`Choose a table from "${i}.${o}"`,{autocomplete:!0,choices:e})}let c=(await a.columns({catalog:i,schema:o,table:s})).map(([e,t,n,r])=>({description:r,extra:n,name:e,type:t})),l=new w;l.column(`Column Name`,`name`),l.column(`Type`,`type`),l.column(`Extra`,`extra`),l.column(`Description`,`description`),l.render(c)}),t}function Ie(){let t=new e(`list-schemas`);return t.description(`Lists the available schemas for the configured catalog`).addOption(N).action(async({catalog:e})=>{let t=Q(),n=e??t.HIVE_CATALOG,r=await new b({auth:{password:t.HIVE_PASSWORD,type:`basic`,username:t.HIVE_USERNAME},catalog:n,host:t.HIVE_HOST,port:t.HIVE_PORT}).schemas({catalog:n}),i=new w;i.column(`Schema Name`,`s`),i.render(r.map(e=>({s:e})))}),t}function Le(){let t=new e(`list-tables`);return t.description(`Lists the available tables for the configured catalog/schema`).addOption(N).addOption(P).action(async({catalog:e,schema:t})=>{let n=Q(),r=e??n.HIVE_CATALOG,i=new b({auth:{password:n.HIVE_PASSWORD,type:`basic`,username:n.HIVE_USERNAME},catalog:r,host:n.HIVE_HOST,port:n.HIVE_PORT}),a=t;if(a===void 0){let e=await i.schemas({catalog:r});a=await C(`Choose a schema from the ${r} catalog`,{autocomplete:!0,choices:e})}let o=await i.tables({catalog:r,schema:a}),s=new w;s.column(`Table Name`,`t`),s.render(o.map(e=>({t:e})))}),t}function Re(){let t=new e(`list-views`);return t.description(`Lists the available views for the configured catalog/schema`).addOption(N).addOption(P).action(async({catalog:e,schema:t})=>{let n=Q(),r=e??n.HIVE_CATALOG,i=new b({auth:{password:n.HIVE_PASSWORD,type:`basic`,username:n.HIVE_USERNAME},catalog:r,host:n.HIVE_HOST,port:n.HIVE_PORT}),a=t;if(a===void 0){let e=await i.schemas({catalog:r});a=await C(`Choose a schema from the ${r} catalog`,{choices:e})}let o=await i.views({catalog:r,schema:a}),s=new w;s.column(`View Name`,`v`),s.render(o.map(e=>({v:e})))}),t}function ze(e){switch(e.replaceAll(/[^a-zA-Z]/gu,``)){case`varchar`:return`String`;case`decimal`:case`double`:case`float`:return`Float`;case`integer`:case`bigint`:return`Integer`;case`boolean`:return`Boolean`;case`timestamp`:return`DateTime`;case`date`:return`Date`;default:return`String`}}function Be(e,t){return typeof t==`string`?{name:e,type:ze(t)}:Array.isArray(t)?{name:e,type:`Array`,items:Ve(t)}:typeof t==`object`&&t?{name:e,type:`Object`,fields:$(t)}:{name:e,type:`String`}}function Ve(e){if(e.length===0)return{type:`String`};let[t]=e;return typeof t==`string`?{type:ze(t)}:typeof t==`object`&&t&&!Array.isArray(t)?{type:`Object`,fields:$(t)}:{type:`String`}}function $(e){let t=[];for(let[n,r]of Object.entries(e))t.push(Be(n,r));return t}function He(e){let{tableName:t,catalog:n,schema:r,parsedColumns:i}=e;return{version:`1.0`,tableName:t,catalog:n,schema:r,fields:$(i),mutation:!1}}function Ue(){let t=new e(`pull`),n=t.description(`Interactive query endpoint generation based on a remote table`).addOption(N).addOption(fe).addOption(P.makeOptionMandatory(!1)).addOption(de.makeOptionMandatory(!1).default([]).argParser((e,t)=>[...t,e])).addOption(pe).addOption(F);return n.action(async e=>{let n=Q(),{skipRegistry:r,sourcePath:i}=e,a=e.catalog??n.HIVE_CATALOG,{schema:o,table:s,type:c}=e,u=i===(process.env.INIT_CWD??process.cwd())?void 0:i,d=M(u),f=new b({auth:{password:n.HIVE_PASSWORD,type:`basic`,username:n.HIVE_USERNAME},catalog:a,host:n.HIVE_HOST,port:n.HIVE_PORT});if(!o){let e=await f.schemas({catalog:a});o=await C(`Choose a schema from the ${a} catalog`,{autocomplete:!0,choices:e})}if(s.length===0&&(c??=await C(`What do you want to see from ${a}/${o}`,{choices:[{label:`Show tables`,value:`tables`},{label:`Show views`,value:`views`}]})),s.length===0){let e=[];e=c===`views`?await f.views({catalog:a,schema:o}):await f.tables({catalog:a,schema:o}),e.length===0&&t.error(D(`There are no tables in schema '${a}.${o}'.`),{exitCode:0}),s=await x(`Choose the tables to pull`,{autocomplete:!0,choices:e,validators:[re.required()]})}for(let e of s){let t=E((await f.columns({catalog:a,schema:o,table:e})).map(e=>ce({keys:[`name`,`type`,`extra`,`description`],values:e})));await je({definition:He({tableName:e,catalog:a,schema:o,parsedColumns:t}),outputDir:l.join(d,`schemas/generated`,a,o,e),skipRegistry:r,sourcePathOverride:u})}}),n}function We(){return new e(`init`).description(`Initialize a lakeql.config.json configuration file`).action(async()=>{let e=A(),t=l.join(e,j);if(r(t)&&await C(`lakeql.config.json already exists. Overwrite?`,{choices:[{label:`Yes`,value:`yes`},{label:`No`,value:`no`}]})===`no`){console.log(O.yellow(`Aborted.`));return}let n=r(l.join(e,`src`)),i;if(n)i=`src`,console.log(O.cyan(`Detected src/ directory — generated code will be placed in src/`));else{let e=await C(`Where should generated code be placed?`,{choices:[{label:`./ (project root)`,value:`.`},{label:`Custom path`,value:`__custom__`}]});i=e,e===`__custom__`&&(i=await S(`Enter the source path (relative to project root):`,{defaultValue:`.`}))}await c(t,`${JSON.stringify({sourcePath:i},null,2)}\n`),console.log(O.green(`Created ${j} at ${t}`))})}async function Ge(){let t=await n(),r=new e;r.configureHelp({sortSubcommands:!0}),r.name(`lakeql-cli`).description(`LakeQL CLI`).version(t.version).addCommand(Ie()).addCommand(Le()).addCommand(Re()).addCommand(Fe()).addCommand(Ue()).addCommand(Me()).addCommand(me()).addCommand(We()),await r.parseAsync()}Ge().catch(()=>{process.exit(1)});export{};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lakeql/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "CLI for introspecting Trino schemas and generating type-safe GraphQL endpoints",
5
5
  "keywords": [
6
6
  "cli",
@@ -55,13 +55,13 @@
55
55
  "ora": "9.4.0",
56
56
  "read-pkg": "10.1.0",
57
57
  "zod": "4.4.3",
58
- "@lakeql/column-parser": "0.1.2",
59
- "@lakeql/helpers": "0.1.2",
60
- "@lakeql/logger": "0.1.2",
61
58
  "@lakeql/file-generator": "0.1.3",
59
+ "@lakeql/column-parser": "0.1.2",
62
60
  "@lakeql/response-transformer": "0.1.2",
61
+ "@lakeql/helpers": "0.1.2",
63
62
  "@lakeql/schema-generator": "0.2.0",
64
- "@lakeql/trino-client": "0.3.0"
63
+ "@lakeql/trino-client": "0.3.0",
64
+ "@lakeql/logger": "0.1.2"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/lodash-es": "4.17.12",