Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@embracesql/postgres

Package Overview
Dependencies
Maintainers
1
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@embracesql/postgres - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

src/generator/pgtype/overrides/geometric/box.ts

10

package.json
{
"name": "@embracesql/postgres",
"version": "0.0.3",
"version": "0.0.4",
"description": "EmbraceSQL shared library for talking to postgres. Used in Node.",

@@ -13,4 +13,5 @@ "type": "module",

"dependencies": {
"@embracesql/shared": "^0.0.3",
"@embracesql/shared": "^0.0.4",
"glob": "^10.3.10",
"object-hash": "^3.0.0",
"pg-connection-string": "^2.6.2",

@@ -20,3 +21,6 @@ "postgres": "^3.4.3",

},
"gitHead": "ce8c43da83ab6e340d337431a8d18e652a127cbd"
"devDependencies": {
"@types/object-hash": "^3.0.6"
},
"gitHead": "343e5761ee3ff99619a2ba34c18139d0ef6240ad"
}

@@ -9,3 +9,14 @@ import { PGAttributes } from "./generator/pgtype/pgattribute";

import { PGTypeEnumValues } from "./generator/pgtype/pgtypeenum";
import { DatabaseNode } from "@embracesql/shared";
import {
ColumnNode,
DatabaseNode,
IndexColumnNode,
IndexNode,
IsNamed,
SchemaNode,
TableNode,
TablesNode,
TypeNode,
TypesNode,
} from "@embracesql/shared";
import pgconnectionstring from "pg-connection-string";

@@ -161,3 +172,65 @@ import postgres from "postgres";

const database = new DatabaseNode(databaseName);
namespaces.forEach((n) => n.addToAST(database));
// ok, this is a bit tricky since - tables and types can cross namespaces
// so the first pass will set up all the schemas from catalog namespaces
// along with their types
namespaces.forEach((n) => {
const schema = new SchemaNode(database, n.namespace);
database.children.push(schema);
const types = new TypesNode(schema);
schema.children.push(types);
// all types in the namespace
n.types.forEach((t) => {
const type = new TypeNode(t.typescriptName, types, t.oid, t);
database.registerType(type.id, type);
types.children.push(type);
});
});
// ok -- we now know all types -- now we have enough information to make tables
namespaces.forEach((n) => {
const schema = database.children.find(
(c) => (c as unknown as IsNamed)?.name === n.namespace,
) as SchemaNode;
if (schema) {
const tables = new TablesNode(schema);
schema.children.push(tables);
n.tables.forEach((t) => {
// the table and ...
const table = new TableNode(tables, t.table.relname);
tables.children.push(table);
// it's columns
t.tableType.attributes.forEach((a) => {
const typeNode = database.resolveType(a.attribute.atttypid);
if (typeNode) {
table.children.push(new ColumnNode(table, a.name, typeNode));
} else {
throw new Error(
`${a.name} cannot find type ${a.attribute.atttypid}`,
);
}
});
// indexes go on the table as well
t.indexes.forEach((i) => {
const index = new IndexNode(
table,
i.name,
i.index.indisunique,
i.index.indisprimary,
);
i.attributes.forEach((a) => {
const typeNode = database.resolveType(a.attribute.atttypid);
if (typeNode) {
index.children.push(new IndexColumnNode(index, a.name, typeNode));
} else {
throw new Error(
`${a.name} cannot find type ${a.attribute.atttypid}`,
);
}
});
table.children.push(index);
});
});
} else {
throw new Error(`cannot find namespace ${n.namespace}`);
}
});

@@ -164,0 +237,0 @@ // now we set up a new sql that can do type marshalling - runtime data

@@ -12,3 +12,3 @@ import { Context } from "../../..";

return `
parse${this.typescriptName}(from: string) {
if (from === null) return null;
if(['t', 'T', 'true', 'True'].includes(from)) return true;

@@ -21,3 +21,2 @@ try {

return false;
}
`;

@@ -31,4 +30,4 @@ }

}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
console.assert(context);
// string it -- yeah I know this is strange -- but it is how the

@@ -35,0 +34,0 @@ // postges protocol works

@@ -22,13 +22,12 @@ import { Context } from "../../../context";

return `
parse${this.typescriptName}(from: string) {
if (from === null) return null;
return Number.parseFloat(from);
}
`;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
console.assert(context);
// string it
if (!(x === undefined) && !(x === null)) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
return `${x}`;

@@ -41,3 +40,3 @@ } else {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
parseFromPostgres(context: Context, x: any) {
parseFromPostgres(context: Context, x: any): bigint | number | null {
if (!(x === undefined) && !(x === null)) {

@@ -58,5 +57,5 @@ return +x;

return `
parse${this.typescriptName}(from: string) {
if (from === null) return null;
if (from === '') return null;
return BigInt(from);
}
`;

@@ -68,31 +67,20 @@ }

return `
export type ${this.typescriptName} = BigInt;
export type ${this.typescriptName} = bigint;
`;
}
}
export class PGTypeBytea extends PGCatalogType {
typescriptTypeParser(context: GenerationContext) {
console.assert(context);
return `
parse${this.typescriptName}(from: string) {
return new Uint8Array(JSON.parse(from));
parseFromPostgres(context: Context, x: unknown) {
if (!(x === undefined) && !(x === null)) {
return BigInt(+x);
} else {
return null;
}
`;
}
typescriptTypeDefinition(context: Context) {
console.assert(context);
return `
export type ${this.typescriptName} = Uint8Array;
`;
}
}
export class PGTypeVector extends PGCatalogType {
export class PGTypeBytea extends PGCatalogType {
typescriptTypeParser(context: GenerationContext) {
console.assert(context);
return `
parse${this.typescriptName}(from: string) {
return new Float32Array(JSON.parse(from));
}
return from ? new Uint8Array(JSON.parse(from)) : null;
`;

@@ -103,5 +91,5 @@ }

return `
export type ${this.typescriptName} = Float32Array;
export type ${this.typescriptName} = Uint8Array;
`;
}
}

@@ -9,5 +9,3 @@ import { GenerationContext } from "../..";

return `
parse${this.typescriptName}(from: string) {
return new URL(from);
}
return from ? new URL(from) : null;
`;

@@ -14,0 +12,0 @@ }

@@ -7,4 +7,13 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */

import { registerOverride } from "./_overrides";
import { GenerationContext, commaSeparatedNumbers } from "@embracesql/shared";
class PGCube extends PGCatalogType {
class PGTypeCube extends PGCatalogType {
typescriptTypeParser(context: GenerationContext) {
console.assert(context);
return `
if (from === null) return null;
const source = Array.isArray(from) ? new Float32Array(from) : JSON.parse(from);
return new Float32Array(source);
`;
}
typescriptTypeDefinition(context: Context) {

@@ -21,4 +30,3 @@ console.assert(context);

*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
console.assert(context);

@@ -29,6 +37,8 @@ // default is just 'a string of it'

// postgres array literal
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return `${Object.values(x)
.map((x) => (x ? x : 0))
.join(",")}`;
if (Array.isArray(x))
return `${Object.values(x)
.map((x) => (x ? x : 0))
.join(",")}`;
// wing it 🪽
return `${x}`;
}

@@ -40,3 +50,3 @@

if (x) {
return JSON.parse(`${x}`);
return new Float32Array(commaSeparatedNumbers.tryParse(`${x}`));
} else {

@@ -48,2 +58,2 @@ return null;

registerOverride("cube", PGCube);
registerOverride("cube", PGTypeCube);
import { Context } from "../../../context";
import { PGCatalogType } from "../pgcatalogtype";
import { registerOverride } from "./_overrides";
import { GenerationContext } from "@embracesql/shared";
class PGDate extends PGCatalogType {
typescriptTypeParser(context: GenerationContext) {
console.assert(context);
return `
if (from === null) return null;
if ((from as unknown) instanceof global.Date) return from;
return new global.Date(from);
`;
}
typescriptTypeDefinition(context: Context) {
console.assert(context);
// date ends up with a type alias
return `

@@ -13,7 +23,7 @@ export type ${this.typescriptName} = JsDate;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
console.assert(context);
// string it
if (x) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
return (x instanceof Date ? x : new Date(`${x}`)).toISOString();

@@ -40,3 +50,5 @@ } else {

registerOverride("date", PGDate);
// TODO: gonna need a real JS 'time' type
registerOverride("time", PGDate);
registerOverride("timetz", PGDate);

@@ -7,11 +7,11 @@ import { PGTypeNumber } from "../base/number";

// yeah -- looks odd -- but registerOverride needs to be defined first
export * from "./name";
export * from "./oid";
export * from "./oidvector";
export * from "./uuid";
export * from "./point";
export * from "./box";
export * from "./line";
export * from "./lseg";
export * from "./int2vector";
// TODO: geometric types need real use cases and parsers to match docs at
// https://www.postgresql.org/docs/current/datatype-geometric.html
export * from "./geometric/point";
export * from "./geometric/box";
export * from "./geometric/circle";
export * from "./geometric/line";
export * from "./geometric/lseg";
export * from "./vector";
export * from "./date";

@@ -18,0 +18,0 @@ export * from "./json";

@@ -16,4 +16,4 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */

// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
console.assert(context);
// string it if we need it

@@ -20,0 +20,0 @@ if (x) {

@@ -10,5 +10,3 @@ import { Context } from "../../../context";

return `
parse${this.typescriptName}(from: string) {
return new UUID(from);
}
return from ? new UUID(from) : null;
`;

@@ -23,5 +21,7 @@ }

serializeToPostgres(context: Context, x: UUID) {
serializeToPostgres(context: Context, x: unknown) {
if (x === null) return null;
if ((x as UUID).uuid) return (x as UUID).uuid;
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return x ? x.uuid : null;
return `${x}`;
}

@@ -28,0 +28,0 @@

@@ -1,6 +0,9 @@

import { GeneratesTypeScriptParser, GenerationContext } from "@embracesql/shared";
import { Context, PostgresTypecast } from "../../context";
import { asDocComment } from "../../util";
import { CatalogRow } from "./pgtype";
import {
GeneratesTypeScriptParser,
GenerationContext,
} from "@embracesql/shared";
import { pascalCase } from "change-case";
import { CatalogRow } from "./pgtype";

@@ -32,8 +35,6 @@ /**

typescriptTypeParser(context: GenerationContext) {
console.assert(context)
console.assert(context);
return `
parse${this.typescriptName}(from: string) {
return from;
}
`
`;
}

@@ -98,12 +99,10 @@

/**
* Override this to get 'to' postgres and interface with the database.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
console.assert(context);
// default is just 'a string of it'
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
if (x === null) return null;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return x;
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
return `${x}`;
}

@@ -110,0 +109,0 @@

@@ -6,3 +6,2 @@ import { Context, TypeFactoryContext } from "../../context";

import { PGTypeComposite } from "./pgtypecomposite";
import { IndexColumnNode, IndexNode, TableNode } from "@embracesql/shared";
import { pascalCase } from "change-case";

@@ -70,15 +69,2 @@ import path from "path";

addToAST(table: TableNode) {
const index = new IndexNode(
table,
this.name,
this.index.indisunique,
this.index.indisprimary,
);
this.attributes.forEach((a) =>
index.children.push(new IndexColumnNode(index, a.name)),
);
table.children.push(index);
}
get name() {

@@ -85,0 +71,0 @@ return `by_${this.attributes.map((a) => a.typescriptName).join("_")}`;

@@ -7,3 +7,2 @@ import { Context } from "../../context";

import { PGTypes } from "./pgtype";
import { DatabaseNode, SchemaNode, TablesNode, TypeNode } from "@embracesql/shared";
import { pascalCase } from "change-case";

@@ -66,13 +65,2 @@

addToAST(database: DatabaseNode) {
// each namespace joins the tree
const schema = new SchemaNode(database, this.namespace);
database.children.push(schema);
const tables = new TablesNode(schema);
schema.children.push(tables);
this.tables.forEach((t) => t.addToAST(tables));
// all types in the namespace
this.types.forEach(t => schema.children.push(new TypeNode(schema, t)))
}
get typescriptName() {

@@ -79,0 +67,0 @@ return PGNamespace.typescriptName(this.namespace);

@@ -12,2 +12,3 @@ import { Context, PostgresProcTypecast } from "../../../context";

import { camelCase, pascalCase } from "change-case";
import hash from "object-hash";
import parsimmon from "parsimmon";

@@ -30,2 +31,3 @@ import path from "path";

pronargdefaults: number;
overloads: number;
};

@@ -69,2 +71,6 @@

get overloaded() {
return Number.parseInt(`${this.proc.overloads}`) > 1;
}
get nspname() {

@@ -75,3 +81,5 @@ return this.proc.nspname;

get typescriptName() {
return pascalCase(this.proc.proname);
const seed = pascalCase(this.proc.proname);
const stem = hash(this.proc.proargtypes.flatMap((x) => x)).substring(0, 4);
return this.overloaded ? `${seed}${stem}` : seed;
}

@@ -78,0 +86,0 @@

@@ -5,3 +5,2 @@ import { Context, TypeFactoryContext } from "../../context";

import { PGTypeComposite } from "./pgtypecomposite";
import { ColumnNode, TableNode, TablesNode } from "@embracesql/shared";
import { pascalCase } from "change-case";

@@ -61,11 +60,2 @@ import path from "path";

addToAST(tables: TablesNode) {
const table = new TableNode(tables, this.table.relname);
tables.children.push(table);
this.tableType.attributes.forEach((a) =>
table.children.push(new ColumnNode(table, a.name)),
);
this.indexes.forEach((i) => i.addToAST(table));
}
get typescriptName() {

@@ -72,0 +62,0 @@ return pascalCase(this.table.relname);

import { TypeFactoryContext } from "../../context";
import { PGTypeText } from "./base/text";
import { overrides } from "./overrides";

@@ -70,2 +71,10 @@ import { PGCatalogType } from "./pgcatalogtype";

}
// there are 'odd' base types that are arrays of scalars but when you
// but are not named like other arrays
// TODO: update registerOverride to allow a function expression
if (catalog.typname === "oidvector")
return PGTypeBase.factory(context, catalog);
if (catalog.typname === "name") return new PGTypeText(catalog);
if (catalog.typtype === "c") return new PGTypeComposite(context, catalog);

@@ -72,0 +81,0 @@ if (catalog.typtype === "e") return new PGTypeEnum(context, catalog);

@@ -6,2 +6,3 @@ import { Context, TypeFactoryContext } from "../../context";

DELIMITER,
GenerationContext,
arrayAttribute,

@@ -12,2 +13,6 @@ escapeArrayValue,

type Props = {
arraySuffix: boolean;
};
/**

@@ -17,11 +22,34 @@ * Arrays of other types are somewhat simple to declare - it is just Array<...>.

export class PGTypeArray extends PGCatalogType {
constructor(context: TypeFactoryContext, catalog: CatalogRow) {
constructor(
context: TypeFactoryContext,
catalog: CatalogRow,
private props: Props = { arraySuffix: true },
) {
super(catalog);
}
/**
* Arrays have ... the word Array...
*/
typescriptTypeParser(context: GenerationContext) {
const elementType = context.database.resolveType(this.catalog.typelem);
if (elementType) {
return `
if (from === null) return null;
const rawArray = JSON.parse(from);
return rawArray.map((e:unknown) => {
return ${elementType.typescriptName}.parse(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
\`\${e}\`
);
});
`;
} else {
throw new Error(
`${this.catalog.typname} could not resolve type of element`,
);
}
}
get typescriptName() {
return `${pascalCase(this.catalog.typname)}Array`;
return `${pascalCase(this.catalog.typname)}${
this.props.arraySuffix ? "Array" : ""
}`;
}

@@ -40,4 +68,3 @@

// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
// passed object

@@ -44,0 +71,0 @@ if (x) {

import { Context, TypeFactoryContext } from "../../context";
import { asDocComment } from "../../util";
import { PGTypeBool } from "./base/bool";
import {
PGTypeBigInt,
PGTypeBytea,
PGTypeNumber,
PGTypeVector,
} from "./base/number";
import { PGTypeBigInt, PGTypeBytea, PGTypeNumber } from "./base/number";
import { PGTypeText, PGTypeTextArray } from "./base/text";

@@ -14,2 +9,3 @@ import { PGTypeUri } from "./base/uri";

import { CatalogRow } from "./pgtype";
import { PGTypeArray } from "./pgtypearray";

@@ -52,4 +48,2 @@ /**

return new PGTypeBytea(catalog);
case "vector":
return new PGTypeVector(catalog);
case "inet":

@@ -59,12 +53,2 @@ return new PGTypeInet(catalog);

return new PGTypeText(catalog);
case "point":
return new PGTypePoint(catalog);
case "box":
return new PGTypePointPair(catalog);
case "path":
return new PGTypePointArray(catalog);
case "polygon":
return new PGTypePointArray(catalog);
case "circle":
return new PGTypeCircle(catalog);
case "aclitem":

@@ -74,6 +58,6 @@ return new PGTypeText(catalog);

return new PGTypeText(catalog);
case "lsn":
case "pg_lsn":
return new PGTypeBigInt(catalog);
case "tsvector":
return new PGTypeTextArray(catalog);
return new PGTypeText(catalog);
case "gtsvector":

@@ -85,2 +69,4 @@ return new PGTypeTextArray(catalog);

return new PGTypeUri(catalog);
case "oidvector":
return new PGTypeArray(context, catalog, { arraySuffix: false });
default:

@@ -126,49 +112,1 @@ // if the db wants to code it as text, so do we

}
class PGTypePoint extends PGTypeBase {
typescriptTypeDefinition(context: Context) {
console.assert(context);
return `
${asDocComment(this.comment)}
export type ${this.typescriptName} = {
x: number;
y: number;
};
`;
}
}
class PGTypePointPair extends PGTypeBase {
typescriptTypeDefinition(context: Context) {
console.assert(context);
return `
${asDocComment(this.comment)}
export type ${this.typescriptName} = {
from: Point;
to: Point;
};
`;
}
}
class PGTypePointArray extends PGTypeBase {
typescriptTypeDefinition(context: Context) {
console.assert(context);
return `
${asDocComment(this.comment)}
export type ${this.typescriptName} = Array<Point>;
`;
}
}
class PGTypeCircle extends PGTypeBase {
typescriptTypeDefinition(context: Context) {
console.assert(context);
return `
${asDocComment(this.comment)}
export type ${this.typescriptName} = {
center: Point;
radius: number;
};
`;
}
}

@@ -137,7 +137,6 @@ import { Context, TypeFactoryContext } from "../../context";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
// make a composite type -- escape the values looked up from the
// passed object
if (x) {
if (typeof x === "object") {
const attributes = this.attributes.map((a) => {

@@ -150,3 +149,3 @@ // hand off the the serializer

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
x[camelCase(a.attribute.attname)],
(x as Record<string, object>)[camelCase(a.attribute.attname)],
);

@@ -153,0 +152,0 @@ // quick escape with regex

@@ -34,4 +34,3 @@ import { Context, TypeFactoryContext } from "../../context";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
serializeToPostgres(context: Context, x: any) {
serializeToPostgres(context: Context, x: unknown) {
// delegate to the base type

@@ -38,0 +37,0 @@ // eslint-disable-next-line @typescript-eslint/no-unsafe-return

@@ -6,4 +6,4 @@ import { GenerationContext } from "..";

} from "../operations/sqlscript";
import { ASTKind, IsNamed, NamespaceVisitor } from "@embracesql/shared";
import { camelCase, pascalCase } from "change-case";
import { generatePrimaryKeyPickers } from "./generatePrimaryKeyPickers";
import { generateTypeParsers } from "./generateTypeParsers";

@@ -84,48 +84,6 @@ /**

// parsing from strings into TS types.
generationBuffer.push(`// begin string parsers`);
context.handlers = {
[ASTKind.Schema]: NamespaceVisitor,
[ASTKind.Type]: {
before: async (context, node) => {
return `export function ${node.parser.typescriptTypeParser(context)}`;
},
},
};
// no skipping schemas for parsing
generationBuffer.push(await context.database.visit({ ...context, skipSchemas: [] }));
generationBuffer.push(`// end string parsers`);
generationBuffer.push(await generateTypeParsers(context));
generationBuffer.push(await generatePrimaryKeyPickers(context));
// primary key 'pickers' used to debounce and hash objects
generationBuffer.push(`// begin primary key pickers`);
context.handlers = {
[ASTKind.Schema]: NamespaceVisitor,
[ASTKind.Table]: {
before: async (_, node) => {
const tableTypeName = `${pascalCase(
(node as unknown as IsNamed)?.name,
)}`;
const generationBuffer = [""];
const primaryKey = node.primaryKey;
if (primaryKey) {
generationBuffer.push(
`export function pickPrimaryKeyFrom${tableTypeName}(value: ${tableTypeName}) : string {`,
);
generationBuffer.push(`return JSON.stringify({`);
primaryKey.columns.forEach((c) =>
generationBuffer.push(
`${camelCase(c.name)}: value.${camelCase(c.name)},`,
),
);
generationBuffer.push(`});`);
generationBuffer.push(`}`);
}
return generationBuffer.join("\n");
},
},
};
generationBuffer.push(await context.database.visit(context));
generationBuffer.push(`// end primary key pickers`);
return generationBuffer.join("\n");
};
export { initializeContext } from "./context";
export type { Context } from "./context";
export * from "./generator";

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc