conjure-lite
Advanced tools
Comparing version 0.0.1 to 0.0.2
{ | ||
"name": "conjure-lite", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"exports": { | ||
@@ -11,18 +11,20 @@ ".": { | ||
"bin": "./bin/conjure-lite.mjs", | ||
"type": "module", | ||
"scripts": { | ||
"prepublish": "tsc" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^20.9.0", | ||
"@types/yargs": "^17.0.31", | ||
"bun-types": "latest", | ||
"dprint": "^0.42.5" | ||
"@typescript-eslint/eslint-plugin": "^6.11.0", | ||
"@typescript-eslint/parser": "^6.11.0", | ||
"conjure-api": "^4.31.0", | ||
"dprint": "^0.42.5", | ||
"eslint": "^8.53.0", | ||
"typescript": "^5.2.2" | ||
}, | ||
"peerDependencies": { | ||
"typescript": "^5.0.0", | ||
"tsup": "^7.2.0" | ||
}, | ||
"dependencies": { | ||
"conjure-api": "^4.31.0", | ||
"prettier": "^3.0.3", | ||
"yargs": "^17.7.2", | ||
"@types/node": "^20.9.0", | ||
"conjure-lite": "." | ||
"dedent": "^1.5.1", | ||
"yargs": "^17.7.2" | ||
} | ||
} |
@@ -1,4 +0,6 @@ | ||
import yargs, { CommandModule } from "yargs"; | ||
import type { CommandModule } from "yargs"; | ||
import yargs from "yargs"; | ||
import { hideBin } from "yargs/helpers"; | ||
import { HandleGenerateArgs } from "./cli/HandleGenerateArgs.js"; | ||
import type { HandleGenerateArgs } from "./cli/HandleGenerateArgs.js"; | ||
import type {} from "node:process"; | ||
@@ -29,4 +31,3 @@ export async function cli() { | ||
await yargs(hideBin(process.argv)) | ||
.command(generate).demandCommand().parseAsync(); | ||
} |
@@ -1,67 +0,13 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import type * as ConjureApi from "conjure-api"; | ||
import * as fs from "node:fs"; | ||
import * as path from "node:path"; | ||
import { CodeGen } from "../codegen/CodeGen.js"; | ||
import { EndpointCodeFile } from "../codegen/EndpointCodeFile.js"; | ||
import { EnumCodeFile } from "../codegen/EnumCodeFile.js"; | ||
import { TypeAliasCodeFile } from "../codegen/TypeAliasCodeFile.js"; | ||
import { UnionCodeFile } from "../codegen/UnionCodeFile.js"; | ||
import { formatTs, writeCodeFile } from "../util/writeCodeFile.js"; | ||
import { HandleGenerateArgs } from "./HandleGenerateArgs.js"; | ||
import type { HandleGenerateArgs } from "./HandleGenerateArgs.js"; | ||
export async function handleGenerate(args: HandleGenerateArgs) { | ||
const ir: ConjureApi.IConjureDefinition = JSON.parse( | ||
await fs.promises.readFile(args.ir, "utf-8"), | ||
await fs.promises.readFile(args.ir, "utf-8") | ||
); | ||
const codeGen = new CodeGen(ir, args); | ||
for (const type of ir.types) { | ||
if (type.type === "object") { | ||
await writeCodeFile( | ||
codeGen.getFilePath(type.object.typeName), | ||
await formatTs(`export interface ${type.object.typeName.name} {}`), | ||
); | ||
} else if (type.type === "alias") { | ||
new TypeAliasCodeFile( | ||
codeGen.getFilePath(type.alias.typeName), | ||
codeGen, | ||
type.alias.typeName.name, | ||
type.alias.alias, | ||
).generate(); | ||
} else if (type.type === "enum") { | ||
new EnumCodeFile( | ||
codeGen.getFilePath(type.enum.typeName), | ||
codeGen, | ||
type, | ||
).generate(); | ||
} else if (type.type === "union") { | ||
new UnionCodeFile( | ||
codeGen.getFilePath(type.union.typeName), | ||
codeGen, | ||
type, | ||
).generate(); | ||
} else { | ||
throw new Error(`Not implemented: ${(type as any).type}`); | ||
} | ||
} | ||
for (const service of ir.services) { | ||
const serviceDir = path.join(codeGen.getPathDir(service.serviceName), service.serviceName.name); | ||
await fs.promises.mkdir(serviceDir, { | ||
recursive: true, | ||
}); | ||
for (const endpoint of service.endpoints) { | ||
const endpointFilePath = `${path.join(serviceDir, endpoint.endpointName)}.ts`; | ||
const endpointCodeFile = new EndpointCodeFile(endpointFilePath, codeGen, service, endpoint); | ||
endpointCodeFile.generate(); | ||
} | ||
await fs.promises.writeFile( | ||
`${args.outDir}/${service.serviceName.name}.ts`, | ||
`export interface ${service.serviceName.name} {}`, | ||
"utf-8", | ||
); | ||
} | ||
await codeGen.generate(); | ||
} |
@@ -1,10 +0,12 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import type * as ConjureApi from "conjure-api"; | ||
import * as fs from "node:fs"; | ||
import * as path from "node:path"; | ||
import { writeCodeFile } from "../util/writeCodeFile.js"; | ||
import { CodeGen } from "./CodeGen.js"; | ||
import type { CodeGen } from "./CodeGen.js"; | ||
export class BaseFileGenerator { | ||
protected readonly filePath: string; | ||
protected readonly codeGen: CodeGen; | ||
protected readonly imports = new Map<string, string>(); | ||
export class BaseFileGenerator<D> { | ||
public readonly def: D; | ||
public readonly filePath: string; | ||
public readonly codeGen: CodeGen; | ||
public readonly imports = new Map<string, string>(); | ||
@@ -14,8 +16,26 @@ constructor( | ||
codeGen: CodeGen, | ||
def: D, | ||
) { | ||
this.filePath = filePath; | ||
this.codeGen = codeGen; | ||
this.def = def; | ||
} | ||
ensureImportForType(type: ConjureApi.IType): void { | ||
ensureImportForType( | ||
type: ConjureApi.IType | ConjureApi.IServiceDefinition | ConjureApi.ITypeName, | ||
): void { | ||
if ("package" in type) { | ||
const importPath = this.getImportModuleSpecifier(type); | ||
this.imports.set( | ||
`${type.package}.${type.name}`, | ||
`import type { ${type.name} } from "${importPath}";`, | ||
); | ||
return; | ||
} | ||
if ("serviceName" in type) { | ||
return this.ensureImportForType(type.serviceName); | ||
} | ||
switch (type.type) { | ||
@@ -29,15 +49,6 @@ case "list": | ||
case "reference": | ||
let importPath = path.relative( | ||
path.dirname(this.filePath), | ||
this.codeGen.getFilePathForImport(type.reference), | ||
); | ||
if (importPath != ".") importPath = `./${importPath}`; | ||
case "reference": { | ||
return this.ensureImportForType(type.reference); | ||
} | ||
this.imports.set( | ||
`${type.reference.package}.${type.reference.name}`, | ||
`import { ${type.reference.name} } from "${importPath}";`, | ||
); | ||
return; | ||
case "optional": | ||
@@ -51,2 +62,17 @@ this.ensureImportForType(type.optional.itemType); | ||
getImportModuleSpecifier(targetFile: string): string; | ||
getImportModuleSpecifier(type: ConjureApi.ITypeName): string; | ||
getImportModuleSpecifier(type: ConjureApi.ITypeName | string) { | ||
let importPath = path.relative( | ||
path.dirname(this.filePath), | ||
this.codeGen.getFilePathForImport(type), | ||
); | ||
if (!importPath.startsWith(".")) importPath = `./${importPath}`; | ||
if (this.codeGen.includeExtensions) { | ||
return importPath; | ||
} | ||
} | ||
getTypeForCode(type: ConjureApi.IType): string { | ||
@@ -100,3 +126,4 @@ this.ensureImportForType(type); | ||
protected async writeFile(body: string) { | ||
async writeFile(body: string) { | ||
await fs.promises.mkdir(path.dirname(this.filePath), { recursive: true }); | ||
await writeCodeFile( | ||
@@ -103,0 +130,0 @@ this.filePath, |
@@ -1,4 +0,4 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import type { IArgumentDefinition, IEndpointDefinition, IParameterType_Query } from "conjure-api"; | ||
export function calculateTemplatedUrlForEndpoint(endpoint: ConjureApi.IEndpointDefinition) { | ||
export function calculateTemplatedUrlForEndpoint(endpoint: IEndpointDefinition) { | ||
const queryArgs = endpoint.args.filter(isQueryArgument); | ||
@@ -45,5 +45,5 @@ const queryPortion = queryArgs.length === 0 | ||
function isQueryArgument( | ||
a: ConjureApi.IArgumentDefinition, | ||
): a is ConjureApi.IArgumentDefinition & { paramType: ConjureApi.IParameterType_Query } { | ||
a: IArgumentDefinition, | ||
): a is IArgumentDefinition & { paramType: IParameterType_Query } { | ||
return a.paramType.type === "query"; | ||
} |
@@ -1,12 +0,27 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import type * as ConjureApi from "conjure-api"; | ||
import * as fs from "node:fs"; | ||
import * as path from "node:path"; | ||
import { HandleGenerateArgs } from "../cli/HandleGenerateArgs.js"; | ||
import type { HandleGenerateArgs } from "../cli/HandleGenerateArgs.js"; | ||
import { findCommonPrefix } from "../util/findCommonPrefix.js"; | ||
import { EndpointCodeFile } from "./EndpointCodeFile.js"; | ||
import { endpointCodeGenerator } from "./EndpointCodeFile.js"; | ||
import { enumCodeGenerator } from "./EnumCodeFile.js"; | ||
import { objectCodeGenerator } from "./ObjectCodeFile.js"; | ||
import { packageIndexCodeGenerator } from "./PackageCodeFile.js"; | ||
import { serviceCodeGenerator } from "./ServiceCodeFile.js"; | ||
import { spreadIntoTypes } from "./spreadIntoTypes.js"; | ||
import { typeAliasCodeGenerator } from "./TypeAliasCodeFile.js"; | ||
import { unionCodeGenerator } from "./UnionCodeFile.js"; | ||
const typeGenerators = { | ||
object: objectCodeGenerator, | ||
alias: typeAliasCodeGenerator, | ||
enum: enumCodeGenerator, | ||
union: unionCodeGenerator, | ||
} as const; | ||
export class CodeGen { | ||
#outDir: string; | ||
#ir: ConjureApi.IConjureDefinition; | ||
#commonBase: string; | ||
ir: ConjureApi.IConjureDefinition; | ||
#commonPackageBase: string; | ||
packages: Set<string>; | ||
@@ -16,33 +31,90 @@ readonly includeExtensions: boolean; | ||
constructor(ir: ConjureApi.IConjureDefinition, args: HandleGenerateArgs) { | ||
this.#ir = ir; | ||
this.ir = ir; | ||
this.#outDir = args.outDir; | ||
this.includeExtensions = args.includeExtensions; | ||
const packages = new Set<string>(); | ||
this.packages = new Set<string>(); | ||
for (const t of ir.types) { | ||
packages.add((t as any)[t.type].typeName.package); | ||
// switch (t.type) { | ||
// case "object": | ||
// packages.add(t.object.typeName.package); | ||
// continue; | ||
// case "alias": | ||
// packages.add(t.alias.typeName.package); | ||
// continue; | ||
// case "enum": | ||
// packages.add(t.enum.typeName.package); | ||
// continue; | ||
// case "union": | ||
// packages.add(t.union.typeName.package); | ||
// continue; | ||
// } | ||
this.packages.add((t as any)[t.type].typeName.package); | ||
} | ||
this.#commonBase = findCommonPrefix(Array.from(packages)); | ||
this.#commonPackageBase = findCommonPrefix(Array.from(this.packages)); | ||
} | ||
getPathDir(typeName: ConjureApi.ITypeName) { | ||
async generate() { | ||
const codeFiles: Array<() => Promise<void>> = []; | ||
const completedPackages = new Set<string>([this.#commonPackageBase]); | ||
// "root package" | ||
codeFiles.push( | ||
packageIndexCodeGenerator( | ||
path.join(this.getPackageDir(this.#commonPackageBase), "index.ts"), | ||
this, | ||
{ | ||
packageName: this.#commonPackageBase, | ||
}, | ||
), | ||
); | ||
for (const fullPackageName of this.packages) { | ||
const partsAfterCommon = fullPackageName.substring(this.#commonPackageBase.length + 1).split( | ||
".", | ||
); | ||
for (let i = 0; i < partsAfterCommon.length; i++) { | ||
const packageName = this.#commonPackageBase + "." | ||
+ partsAfterCommon.slice(0, i + 1).join("."); | ||
if (completedPackages.has(packageName)) continue; | ||
const packagePath = this.getPackageDir(packageName); | ||
await fs.promises.mkdir(packagePath, { recursive: true }); | ||
codeFiles.push( | ||
packageIndexCodeGenerator(path.join(packagePath, "index.ts"), this, { | ||
packageName: packageName, | ||
}), | ||
); | ||
} | ||
} | ||
for (const type of this.ir.types) { | ||
// Typescript does not express this situation well | ||
// `type[type.type]` is the value portion of the enum | ||
const valuePortion = spreadIntoTypes(type); | ||
codeFiles.push(typeGenerators[type.type]( | ||
this.getFilePath(valuePortion.typeName), | ||
this, | ||
valuePortion as any, | ||
)); | ||
} | ||
for (const service of this.ir.services) { | ||
const serviceDir = this.getServiceDir(service); | ||
await fs.promises.mkdir(serviceDir, { | ||
recursive: true, | ||
}); | ||
codeFiles.push( | ||
serviceCodeGenerator( | ||
this.getFilePath(service.serviceName), | ||
this, | ||
service, | ||
), | ||
); | ||
for (const endpoint of service.endpoints) { | ||
codeFiles.push( | ||
endpointCodeGenerator(this.getEndpointPath(service, endpoint), this, endpoint), | ||
); | ||
} | ||
} | ||
await Promise.all(codeFiles.map(a => a())); | ||
} | ||
getPackageDir(fullPackage: string) { | ||
return path.join( | ||
this.#outDir, | ||
...(typeName.package.substring(this.#commonBase.length).split(".")), | ||
...fullPackage.substring(this.#commonPackageBase.length).split("."), | ||
); | ||
@@ -52,28 +124,31 @@ } | ||
getFilePath(typeName: ConjureApi.ITypeName) { | ||
return `${this.getFilePathWithoutExtension(typeName)}.ts`; | ||
return `${path.join(this.getPackageDir(typeName.package), `${typeName.name}.ts`)}`; | ||
} | ||
getFilePathWithoutExtension(typeName: ConjureApi.ITypeName) { | ||
return path.join( | ||
this.getPathDir(typeName), | ||
`${typeName.name}`, | ||
); | ||
getFilePathForImport(typeName: ConjureApi.ITypeName | string) { | ||
const withoutExt = typeof typeName === "string" | ||
? path.join(path.dirname(typeName), path.basename(typeName, path.extname(typeName))) | ||
: path.join(this.getPackageDir(typeName.package), `${typeName.name}`); | ||
return this.includeExtensions ? withoutExt + ".js" : withoutExt; | ||
} | ||
getFilePathForImport(typeName: ConjureApi.ITypeName) { | ||
getServiceDir(service: ConjureApi.IServiceDefinition) { | ||
return path.join( | ||
this.getPathDir(typeName), | ||
`${typeName.name}${this.includeExtensions ? ".js" : ""}`, | ||
this.getPackageDir(service.serviceName.package), | ||
service.serviceName.name, | ||
); | ||
} | ||
async doThing(service: ConjureApi.IServiceDefinition, endpoint: ConjureApi.IEndpointDefinition) { | ||
const serviceDir = path.join(this.getPathDir(service.serviceName), service.serviceName.name); | ||
await fs.promises.mkdir(serviceDir, { | ||
recursive: true, | ||
}); | ||
const endpointFilePath = `${path.join(serviceDir, endpoint.endpointName)}.ts`; | ||
const endpointCodeFile = new EndpointCodeFile(endpointFilePath, this, service, endpoint); | ||
getEndpointPath( | ||
service: ConjureApi.IServiceDefinition, | ||
endpoint: ConjureApi.IEndpointDefinition, | ||
) { | ||
return `${ | ||
path.join( | ||
this.getServiceDir(service), | ||
endpoint.endpointName, | ||
) | ||
}.ts`; | ||
} | ||
} |
@@ -1,39 +0,26 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import { BaseFileGenerator } from "./BaseFileGenerator.js"; | ||
import type { IEndpointDefinition, IType } from "conjure-api"; | ||
import dedent from "dedent"; | ||
import { calculateTemplatedUrlForEndpoint } from "./calculateTemplatedUrlForEndpoint.js"; | ||
import { CodeGen } from "./CodeGen.js"; | ||
import { generatorFactory } from "./generatorFactory.js"; | ||
export class EndpointCodeFile extends BaseFileGenerator { | ||
#service: ConjureApi.IServiceDefinition; | ||
#endpoint: ConjureApi.IEndpointDefinition; | ||
export const endpointCodeGenerator = generatorFactory<IEndpointDefinition>( | ||
async function() { | ||
const templatedUrl = calculateTemplatedUrlForEndpoint(this.def); | ||
constructor( | ||
filePath: string, | ||
codeGen: CodeGen, | ||
service: ConjureApi.IServiceDefinition, | ||
endpoint: ConjureApi.IEndpointDefinition, | ||
) { | ||
super(filePath, codeGen); | ||
this.#service = service; | ||
this.#endpoint = endpoint; | ||
} | ||
async generate() { | ||
let endpointSource = ""; | ||
const templatedUrl = calculateTemplatedUrlForEndpoint(this.#endpoint); | ||
for (const q of this.#endpoint.args) { | ||
endpointSource += this.ensureImportForType(q.type); | ||
for (const q of this.def.args) { | ||
this.ensureImportForType(q.type); | ||
} | ||
if (this.#endpoint.returns) { | ||
this.ensureImportForType(this.#endpoint.returns); | ||
if (this.def.returns) { | ||
this.ensureImportForType(this.def.returns); | ||
} | ||
const bodyArg = this.#endpoint.args.find(a => a.paramType.type === "body"); | ||
const bodyArg = this.def.args.find(a => a.paramType.type === "body"); | ||
const bodyArgContentType = getContentType(bodyArg?.type); | ||
const acceptContentType = getContentType(this.#endpoint.returns); | ||
const acceptContentType = getContentType(this.def.returns); | ||
this.imports.set("#marker", `import {conjureFetch, type ConjureContext} from "conjure-lite"`); | ||
this.imports.set( | ||
"conjure-lite", | ||
`import { conjureFetch, type ConjureContext } from "conjure-lite"`, | ||
); | ||
@@ -43,3 +30,3 @@ const args = [ | ||
templatedUrl, | ||
`"${this.#endpoint.httpMethod}"`, | ||
`"${this.def.httpMethod}"`, | ||
bodyArg?.argName, | ||
@@ -57,15 +44,15 @@ bodyArgContentType === "application/json" ? undefined : bodyArgContentType, | ||
const functionSource = ` | ||
export async function ${this.#endpoint.endpointName}(ctx: ConjureContext, ${ | ||
this.#endpoint.args.map(a => `${a.argName}: ${this.getTypeForCode(a.type)}`) | ||
}): Promise<${this.#endpoint.returns ? this.getTypeForCode(this.#endpoint.returns) : "void"}> { | ||
return conjureFetch(${args.join(",")}) | ||
} | ||
`; | ||
const functionSource = dedent` | ||
export async function ${this.def.endpointName}(ctx: ConjureContext, ${ | ||
this.def.args.map(a => `${a.argName}: ${this.getTypeForCode(a.type)}`).join(`, `) | ||
}): Promise<${this.def.returns ? this.getTypeForCode(this.def.returns) : "void"}> { | ||
return conjureFetch(${args.join(",")}) | ||
} | ||
`; | ||
await this.writeFile(functionSource); | ||
} | ||
} | ||
}, | ||
); | ||
export function getContentType(arg: ConjureApi.IType | undefined | null) { | ||
export function getContentType(arg: IType | undefined | null) { | ||
return (arg | ||
@@ -78,4 +65,4 @@ && (isBinary(arg) | ||
function isBinary(type: ConjureApi.IType) { | ||
function isBinary(type: IType) { | ||
return type.type === "primitive" && type.primitive === "BINARY"; | ||
} |
@@ -1,30 +0,12 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import { BaseFileGenerator } from "./BaseFileGenerator.js"; | ||
import { CodeGen } from "./CodeGen.js"; | ||
import type { IEnumDefinition } from "conjure-api"; | ||
import { generatorFactory } from "./generatorFactory.js"; | ||
export class EnumCodeFile extends BaseFileGenerator { | ||
def: ConjureApi.ITypeDefinition_Enum; | ||
constructor( | ||
filePath: string, | ||
codeGen: CodeGen, | ||
def: ConjureApi.ITypeDefinition_Enum, | ||
) { | ||
super(filePath, codeGen); | ||
this.def = def; | ||
} | ||
get name() { | ||
return this.def.enum.typeName.name; | ||
} | ||
async generate() { | ||
export const enumCodeGenerator = generatorFactory<IEnumDefinition>( | ||
async function() { | ||
const { typeName: { name }, values } = this.def; | ||
const source = ` | ||
export type ${this.name} = ${this.def.enum.values.map(v => `"${v.value}"`).join("|")} | ||
`; | ||
export type ${name} = ${values.map(({ value }) => `"${value}"`).join("|")};\n`; | ||
await this.writeFile(source); | ||
} | ||
} | ||
}, | ||
); |
@@ -1,27 +0,12 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import { BaseFileGenerator } from "./BaseFileGenerator.js"; | ||
import { CodeGen } from "./CodeGen.js"; | ||
import type { IAliasDefinition } from "conjure-api"; | ||
import { generatorFactory } from "./generatorFactory.js"; | ||
export class TypeAliasCodeFile extends BaseFileGenerator { | ||
name: string; | ||
target: ConjureApi.IType; | ||
constructor( | ||
filePath: string, | ||
codeGen: CodeGen, | ||
name: string, | ||
target: ConjureApi.IType, | ||
) { | ||
super(filePath, codeGen); | ||
this.name = name; | ||
this.target = target; | ||
} | ||
export const typeAliasCodeGenerator = generatorFactory<IAliasDefinition>( | ||
async function() { | ||
const { typeName: { name }, alias } = this.def; | ||
async generate() { | ||
const source = ` | ||
export type ${this.name} = ${this.getTypeForCode(this.target)} | ||
`; | ||
const source = `export type ${name} = ${this.getTypeForCode(alias)};\n`; | ||
await this.writeFile(source); | ||
} | ||
} | ||
}, | ||
); |
@@ -1,40 +0,26 @@ | ||
import * as ConjureApi from "conjure-api"; | ||
import { BaseFileGenerator } from "./BaseFileGenerator.js"; | ||
import { CodeGen } from "./CodeGen.js"; | ||
import type { IFieldDefinition, IUnionDefinition } from "conjure-api"; | ||
import dedent from "dedent"; | ||
import { generatorFactory } from "./generatorFactory.js"; | ||
export class UnionCodeFile extends BaseFileGenerator { | ||
def: ConjureApi.ITypeDefinition_Union; | ||
export const unionCodeGenerator = generatorFactory<IUnionDefinition>( | ||
async function() { | ||
const { typeName: { name }, union } = this.def; | ||
constructor( | ||
filePath: string, | ||
codeGen: CodeGen, | ||
def: ConjureApi.ITypeDefinition_Union, | ||
) { | ||
super(filePath, codeGen); | ||
const createUnionInterface = (u: IFieldDefinition) => { | ||
return dedent` | ||
export interface ${name}_${u.fieldName} { | ||
type: "${u.fieldName}"; | ||
${u.fieldName}: ${this.getTypeForCode(u.type)} | ||
}\n`; | ||
}; | ||
this.def = def; | ||
} | ||
const source = dedent` | ||
${union.map(createUnionInterface).join("\n")} | ||
get name() { | ||
return this.def.union.typeName.name; | ||
} | ||
async generate() { | ||
const source = ` | ||
${ | ||
this.def.union.union.map(u => { | ||
return ` | ||
export interface ${this.name}_${u.fieldName} { | ||
type: "${u.fieldName}"; | ||
${u.fieldName}: ${this.getTypeForCode(u.type)} | ||
} `; | ||
}) | ||
} | ||
export type ${this.name} = ${this.def.union.union.map(u => `${this.name}_${u.fieldName}`)} | ||
export type ${name} = ${union.map(u => `${name}_${u.fieldName}`).join(" | ")} | ||
`; | ||
await this.writeFile(source); | ||
} | ||
} | ||
}, | ||
); |
@@ -1,2 +0,2 @@ | ||
import { ConjureContext } from "."; | ||
import type { ConjureContext } from "./ConjureContext.js"; | ||
@@ -23,2 +23,3 @@ export async function conjureFetch<T>( | ||
) { | ||
// | ||
} else { | ||
@@ -28,3 +29,3 @@ body = JSON.stringify(body); | ||
} | ||
const response = await fetchFn(url, { | ||
const response = await fetchFn(`${basePath}/${url}`, { | ||
method, | ||
@@ -31,0 +32,0 @@ credentials: "same-origin", |
export { conjureFetch } from "./conjureFetch.js"; | ||
export interface ConjureContext { | ||
fetchFn: typeof fetch; | ||
basePath: string; | ||
} | ||
export type { ConjureContext } from "./ConjureContext.js"; |
export function findCommonPrefix(strings: Array<string>) { | ||
for (let stringIndex = 0; stringIndex < strings[0].length; stringIndex++) { | ||
for (let i = 1; i < strings.length; i++) { | ||
if (strings[0][stringIndex] != strings[i][stringIndex]) { | ||
return strings[0].substring(0, stringIndex); | ||
const splitStrings = strings.map(s => s.split(".")); | ||
for (let i = 0; i < splitStrings[0].length; i++) { | ||
for (let j = 1; j < splitStrings.length; j++) { | ||
if (splitStrings[0][i] != splitStrings[j][i]) { | ||
return splitStrings[0].slice(0, i).join("."); | ||
} | ||
@@ -7,0 +9,0 @@ } |
import * as fs from "node:fs"; | ||
import { format } from "prettier"; | ||
export async function formatTs(code: string) { | ||
try { | ||
return await format(code, { | ||
parser: "typescript", | ||
tabWidth: 2, | ||
printWidth: 80, | ||
}); | ||
} catch (e) { | ||
console.log(e); | ||
return code; | ||
} | ||
} | ||
export async function writeCodeFile(path: string, code: string) { | ||
return await fs.promises.writeFile( | ||
path, | ||
await formatTs(code), | ||
code, | ||
"utf-8", | ||
); | ||
} |
@@ -5,3 +5,3 @@ { | ||
"outDir": "lib", | ||
"lib": ["ESNext"], | ||
"lib": ["ESNext", "webworker"], | ||
"module": "Node16", | ||
@@ -17,3 +17,8 @@ "target": "ESNext", | ||
"forceConsistentCasingInFileNames": true, | ||
"noEmitOnError": false | ||
"noEmitOnError": false, | ||
"types": [], | ||
"paths": { | ||
"conjure-lite": ["./src"], | ||
"node:*": ["./node_modules/@types/node/*.d.ts"], | ||
} | ||
}, | ||
@@ -20,0 +25,0 @@ "exclude": ["adsrc/tmp/**/*"], |
23330
2
27
698
Yes
8
+ Addeddedent@^1.5.1
+ Addeddedent@1.5.3(transitive)
- Removed@types/node@^20.9.0
- Removedconjure-api@^4.31.0
- Removedconjure-lite@.
- Removedprettier@^3.0.3
- Removed@esbuild/aix-ppc64@0.19.12(transitive)
- Removed@esbuild/android-arm@0.19.12(transitive)
- Removed@esbuild/android-arm64@0.19.12(transitive)
- Removed@esbuild/android-x64@0.19.12(transitive)
- Removed@esbuild/darwin-arm64@0.19.12(transitive)
- Removed@esbuild/darwin-x64@0.19.12(transitive)
- Removed@esbuild/freebsd-arm64@0.19.12(transitive)
- Removed@esbuild/freebsd-x64@0.19.12(transitive)
- Removed@esbuild/linux-arm@0.19.12(transitive)
- Removed@esbuild/linux-arm64@0.19.12(transitive)
- Removed@esbuild/linux-ia32@0.19.12(transitive)
- Removed@esbuild/linux-loong64@0.19.12(transitive)
- Removed@esbuild/linux-mips64el@0.19.12(transitive)
- Removed@esbuild/linux-ppc64@0.19.12(transitive)
- Removed@esbuild/linux-riscv64@0.19.12(transitive)
- Removed@esbuild/linux-s390x@0.19.12(transitive)
- Removed@esbuild/linux-x64@0.19.12(transitive)
- Removed@esbuild/netbsd-x64@0.19.12(transitive)
- Removed@esbuild/openbsd-x64@0.19.12(transitive)
- Removed@esbuild/sunos-x64@0.19.12(transitive)
- Removed@esbuild/win32-arm64@0.19.12(transitive)
- Removed@esbuild/win32-ia32@0.19.12(transitive)
- Removed@esbuild/win32-x64@0.19.12(transitive)
- Removed@isaacs/cliui@8.0.2(transitive)
- Removed@jridgewell/gen-mapping@0.3.8(transitive)
- Removed@jridgewell/resolve-uri@3.1.2(transitive)
- Removed@jridgewell/set-array@1.2.1(transitive)
- Removed@jridgewell/sourcemap-codec@1.5.0(transitive)
- Removed@jridgewell/trace-mapping@0.3.25(transitive)
- Removed@nodelib/fs.scandir@2.1.5(transitive)
- Removed@nodelib/fs.stat@2.0.5(transitive)
- Removed@nodelib/fs.walk@1.2.8(transitive)
- Removed@pkgjs/parseargs@0.11.0(transitive)
- Removed@rollup/rollup-android-arm-eabi@4.30.1(transitive)
- Removed@rollup/rollup-android-arm64@4.30.1(transitive)
- Removed@rollup/rollup-darwin-arm64@4.30.1(transitive)
- Removed@rollup/rollup-darwin-x64@4.30.1(transitive)
- Removed@rollup/rollup-freebsd-arm64@4.30.1(transitive)
- Removed@rollup/rollup-freebsd-x64@4.30.1(transitive)
- Removed@rollup/rollup-linux-arm-gnueabihf@4.30.1(transitive)
- Removed@rollup/rollup-linux-arm-musleabihf@4.30.1(transitive)
- Removed@rollup/rollup-linux-arm64-gnu@4.30.1(transitive)
- Removed@rollup/rollup-linux-arm64-musl@4.30.1(transitive)
- Removed@rollup/rollup-linux-loongarch64-gnu@4.30.1(transitive)
- Removed@rollup/rollup-linux-powerpc64le-gnu@4.30.1(transitive)
- Removed@rollup/rollup-linux-riscv64-gnu@4.30.1(transitive)
- Removed@rollup/rollup-linux-s390x-gnu@4.30.1(transitive)
- Removed@rollup/rollup-linux-x64-gnu@4.30.1(transitive)
- Removed@rollup/rollup-linux-x64-musl@4.30.1(transitive)
- Removed@rollup/rollup-win32-arm64-msvc@4.30.1(transitive)
- Removed@rollup/rollup-win32-ia32-msvc@4.30.1(transitive)
- Removed@rollup/rollup-win32-x64-msvc@4.30.1(transitive)
- Removed@types/estree@1.0.6(transitive)
- Removed@types/node@20.17.12(transitive)
- Removedansi-regex@6.1.0(transitive)
- Removedansi-styles@6.2.1(transitive)
- Removedany-promise@1.3.0(transitive)
- Removedanymatch@3.1.3(transitive)
- Removedarray-union@2.1.0(transitive)
- Removedbalanced-match@1.0.2(transitive)
- Removedbinary-extensions@2.3.0(transitive)
- Removedbrace-expansion@2.0.1(transitive)
- Removedbraces@3.0.3(transitive)
- Removedbundle-require@4.2.1(transitive)
- Removedcac@6.7.14(transitive)
- Removedchokidar@3.6.0(transitive)
- Removedcommander@4.1.1(transitive)
- Removedconjure-api@4.50.0(transitive)
- Removedconjure-client@2.11.0(transitive)
- Removedcross-spawn@7.0.6(transitive)
- Removeddebug@4.4.0(transitive)
- Removeddir-glob@3.0.1(transitive)
- Removedeastasianwidth@0.2.0(transitive)
- Removedemoji-regex@9.2.2(transitive)
- Removedesbuild@0.19.12(transitive)
- Removedexeca@5.1.1(transitive)
- Removedfast-glob@3.3.3(transitive)
- Removedfastq@1.18.0(transitive)
- Removedfill-range@7.1.1(transitive)
- Removedforeground-child@3.3.0(transitive)
- Removedfsevents@2.3.3(transitive)
- Removedget-stream@6.0.1(transitive)
- Removedglob@10.4.5(transitive)
- Removedglob-parent@5.1.2(transitive)
- Removedglobby@11.1.0(transitive)
- Removedhuman-signals@2.1.0(transitive)
- Removedignore@5.3.2(transitive)
- Removedis-binary-path@2.1.0(transitive)
- Removedis-extglob@2.1.1(transitive)
- Removedis-glob@4.0.3(transitive)
- Removedis-number@7.0.0(transitive)
- Removedis-stream@2.0.1(transitive)
- Removedisexe@2.0.0(transitive)
- Removedjackspeak@3.4.3(transitive)
- Removedjoycon@3.1.1(transitive)
- Removedlilconfig@3.1.3(transitive)
- Removedlines-and-columns@1.2.4(transitive)
- Removedload-tsconfig@0.2.5(transitive)
- Removedlodash.sortby@4.7.0(transitive)
- Removedlru-cache@10.4.3(transitive)
- Removedmerge-stream@2.0.0(transitive)
- Removedmerge2@1.4.1(transitive)
- Removedmicromatch@4.0.8(transitive)
- Removedmimic-fn@2.1.0(transitive)
- Removedminimatch@9.0.5(transitive)
- Removedminipass@7.1.2(transitive)
- Removedms@2.1.3(transitive)
- Removedmz@2.7.0(transitive)
- Removednormalize-path@3.0.0(transitive)
- Removednpm-run-path@4.0.1(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedonetime@5.1.2(transitive)
- Removedpackage-json-from-dist@1.0.1(transitive)
- Removedpath-key@3.1.1(transitive)
- Removedpath-scurry@1.11.1(transitive)
- Removedpath-type@4.0.0(transitive)
- Removedpicomatch@2.3.1(transitive)
- Removedpirates@4.0.6(transitive)
- Removedpostcss-load-config@4.0.2(transitive)
- Removedprettier@3.4.2(transitive)
- Removedpunycode@2.3.1(transitive)
- Removedqueue-microtask@1.2.3(transitive)
- Removedreaddirp@3.6.0(transitive)
- Removedresolve-from@5.0.0(transitive)
- Removedreusify@1.0.4(transitive)
- Removedrollup@4.30.1(transitive)
- Removedrun-parallel@1.2.0(transitive)
- Removedshebang-command@2.0.0(transitive)
- Removedshebang-regex@3.0.0(transitive)
- Removedsignal-exit@3.0.74.1.0(transitive)
- Removedslash@3.0.0(transitive)
- Removedsource-map@0.8.0-beta.0(transitive)
- Removedstring-width@5.1.2(transitive)
- Removedstrip-ansi@7.1.0(transitive)
- Removedstrip-final-newline@2.0.0(transitive)
- Removedsucrase@3.35.0(transitive)
- Removedthenify@3.3.1(transitive)
- Removedthenify-all@1.6.0(transitive)
- Removedto-regex-range@5.0.1(transitive)
- Removedtr46@1.0.1(transitive)
- Removedtree-kill@1.2.2(transitive)
- Removedts-interface-checker@0.1.13(transitive)
- Removedtsup@7.3.0(transitive)
- Removedtypescript@5.7.3(transitive)
- Removedundici-types@6.19.8(transitive)
- Removedweb-streams-polyfill@3.3.3(transitive)
- Removedwebidl-conversions@4.0.2(transitive)
- Removedwhatwg-url@7.1.0(transitive)
- Removedwhich@2.0.2(transitive)
- Removedwrap-ansi@8.1.0(transitive)
- Removedyaml@2.7.0(transitive)