Initial commit - Event Planner application

This commit is contained in:
mberlin
2026-03-18 14:55:56 -03:00
commit 86d779eb4d
7548 changed files with 1006324 additions and 0 deletions

21
node_modules/@mikro-orm/postgresql/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Martin Adámek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,8 @@
import { type PoolConfig } from 'pg';
import { PostgresDialect } from 'kysely';
import { AbstractSqlConnection } from '@mikro-orm/sql';
/** PostgreSQL database connection using the `pg` driver. */
export declare class PostgreSqlConnection extends AbstractSqlConnection {
createKyselyDialect(overrides: PoolConfig): PostgresDialect;
mapOptions(overrides: PoolConfig): PoolConfig;
}

View File

@@ -0,0 +1,38 @@
import { Pool, TypeOverrides } from 'pg';
import Cursor from 'pg-cursor';
import { PostgresDialect } from 'kysely';
import array from 'postgres-array';
import { AbstractSqlConnection, Utils } from '@mikro-orm/sql';
/** PostgreSQL database connection using the `pg` driver. */
export class PostgreSqlConnection extends AbstractSqlConnection {
createKyselyDialect(overrides) {
const options = this.mapOptions(overrides);
return new PostgresDialect({
pool: new Pool(options),
cursor: Cursor,
onCreateConnection: this.options.onCreateConnection ?? this.config.get('onCreateConnection'),
});
}
mapOptions(overrides) {
const ret = { ...this.getConnectionOptions() };
const pool = this.config.get('pool');
Utils.defaultValue(ret, 'max', pool?.max);
Utils.defaultValue(ret, 'idleTimeoutMillis', pool?.idleTimeoutMillis);
// use `select typname, oid, typarray from pg_type order by oid` to get the list of OIDs
const types = new TypeOverrides();
[
1082, // date
1114, // timestamp
1184, // timestamptz
1186, // interval
].forEach(oid => types.setTypeParser(oid, str => str));
[
1182, // date[]
1115, // timestamp[]
1185, // timestamptz[]
1187, // interval[]
].forEach(oid => types.setTypeParser(oid, str => array.parse(str)));
ret.types = types;
return Utils.mergeConfig(ret, overrides);
}
}

View File

@@ -0,0 +1,13 @@
import { type Configuration, type Constructor, EntityManagerType } from '@mikro-orm/core';
import { AbstractSqlDriver } from '@mikro-orm/sql';
import { PostgreSqlConnection } from './PostgreSqlConnection.js';
import { PostgreSqlMikroORM } from './PostgreSqlMikroORM.js';
import { PostgreSqlEntityManager } from './PostgreSqlEntityManager.js';
/** Database driver for PostgreSQL. */
export declare class PostgreSqlDriver extends AbstractSqlDriver<PostgreSqlConnection> {
[EntityManagerType]: PostgreSqlEntityManager<this>;
constructor(config: Configuration);
createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
/** @inheritDoc */
getORMClass(): Constructor<PostgreSqlMikroORM>;
}

21
node_modules/@mikro-orm/postgresql/PostgreSqlDriver.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
import { EntityManagerType } from '@mikro-orm/core';
import { AbstractSqlDriver } from '@mikro-orm/sql';
import { PostgreSqlConnection } from './PostgreSqlConnection.js';
import { PostgreSqlPlatform } from './PostgreSqlPlatform.js';
import { PostgreSqlMikroORM } from './PostgreSqlMikroORM.js';
import { PostgreSqlEntityManager } from './PostgreSqlEntityManager.js';
/** Database driver for PostgreSQL. */
export class PostgreSqlDriver extends AbstractSqlDriver {
[EntityManagerType];
constructor(config) {
super(config, new PostgreSqlPlatform(), PostgreSqlConnection, ['kysely', 'pg']);
}
createEntityManager(useContext) {
const EntityManagerClass = this.config.get('entityManager', PostgreSqlEntityManager);
return new EntityManagerClass(this.config, this, this.metadata, useContext);
}
/** @inheritDoc */
getORMClass() {
return PostgreSqlMikroORM;
}
}

View File

@@ -0,0 +1,23 @@
import { type EntityName } from '@mikro-orm/core';
import { SqlEntityManager } from '@mikro-orm/sql';
import type { PostgreSqlDriver } from './PostgreSqlDriver.js';
/**
* @inheritDoc
*/
export declare class PostgreSqlEntityManager<
Driver extends PostgreSqlDriver = PostgreSqlDriver,
> extends SqlEntityManager<Driver> {
/**
* Refreshes a materialized view.
*
* @param entityName - The entity name or class of the materialized view
* @param options - Optional settings
* @param options.concurrently - If true, refreshes the view concurrently (requires a unique index on the view)
*/
refreshMaterializedView<Entity extends object>(
entityName: EntityName<Entity>,
options?: {
concurrently?: boolean;
},
): Promise<void>;
}

View File

@@ -0,0 +1,23 @@
import { SqlEntityManager } from '@mikro-orm/sql';
/**
* @inheritDoc
*/
export class PostgreSqlEntityManager extends SqlEntityManager {
/**
* Refreshes a materialized view.
*
* @param entityName - The entity name or class of the materialized view
* @param options - Optional settings
* @param options.concurrently - If true, refreshes the view concurrently (requires a unique index on the view)
*/
async refreshMaterializedView(entityName, options) {
const meta = this.getMetadata(entityName);
if (!meta.view || !meta.materialized) {
throw new Error(`Entity ${meta.className} is not a materialized view`);
}
const helper = this.getDriver().getPlatform().getSchemaHelper();
const schema = meta.schema ?? this.config.get('schema');
const sql = helper.refreshMaterializedView(meta.tableName, schema, options?.concurrently);
await this.execute(sql);
}
}

View File

@@ -0,0 +1,58 @@
import {
type AnyEntity,
type EntityClass,
type EntitySchema,
MikroORM,
type Options,
type IDatabaseDriver,
type EntityManager,
type EntityManagerType,
} from '@mikro-orm/core';
import { PostgreSqlDriver } from './PostgreSqlDriver.js';
import type { PostgreSqlEntityManager } from './PostgreSqlEntityManager.js';
/** Configuration options for the PostgreSQL driver. */
export type PostgreSqlOptions<
EM extends PostgreSqlEntityManager = PostgreSqlEntityManager,
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
| string
| EntityClass<AnyEntity>
| EntitySchema
)[],
> = Partial<Options<PostgreSqlDriver, EM, Entities>>;
/** Creates a type-safe configuration object for the PostgreSQL driver. */
export declare function definePostgreSqlConfig<
EM extends PostgreSqlEntityManager = PostgreSqlEntityManager,
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
| string
| EntityClass<AnyEntity>
| EntitySchema
)[],
>(options: Partial<Options<PostgreSqlDriver, EM, Entities>>): Partial<Options<PostgreSqlDriver, EM, Entities>>;
/**
* @inheritDoc
*/
export declare class PostgreSqlMikroORM<
EM extends PostgreSqlEntityManager = PostgreSqlEntityManager,
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
| string
| EntityClass<AnyEntity>
| EntitySchema
)[],
> extends MikroORM<PostgreSqlDriver, EM, Entities> {
/**
* @inheritDoc
*/
static init<
D extends IDatabaseDriver = PostgreSqlDriver,
EM extends EntityManager<D> = D[typeof EntityManagerType] & EntityManager<D>,
Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (
| string
| EntityClass<AnyEntity>
| EntitySchema
)[],
>(options: Partial<Options<D, EM, Entities>>): Promise<MikroORM<D, EM, Entities>>;
/**
* @inheritDoc
*/
constructor(options: Partial<Options<PostgreSqlDriver, EM, Entities>>);
}

View File

@@ -0,0 +1,23 @@
import { defineConfig, MikroORM } from '@mikro-orm/core';
import { PostgreSqlDriver } from './PostgreSqlDriver.js';
/** Creates a type-safe configuration object for the PostgreSQL driver. */
export function definePostgreSqlConfig(options) {
return defineConfig({ driver: PostgreSqlDriver, ...options });
}
/**
* @inheritDoc
*/
export class PostgreSqlMikroORM extends MikroORM {
/**
* @inheritDoc
*/
static async init(options) {
return super.init(definePostgreSqlConfig(options));
}
/**
* @inheritDoc
*/
constructor(options) {
super(definePostgreSqlConfig(options));
}
}

View File

@@ -0,0 +1,13 @@
import { type IPostgresInterval } from 'postgres-interval';
import { BasePostgreSqlPlatform } from '@mikro-orm/sql';
/** Platform implementation for PostgreSQL. */
export declare class PostgreSqlPlatform extends BasePostgreSqlPlatform {
convertIntervalToJSValue(value: string): unknown;
convertIntervalToDatabaseValue(value: IPostgresInterval): unknown;
unmarshallArray(value: string): string[];
escape(value: any): string;
/**
* @inheritDoc
*/
parseDate(value: string | number): Date;
}

View File

@@ -0,0 +1,58 @@
import { Client } from 'pg';
import array from 'postgres-array';
import parseDate from 'postgres-date';
import PostgresInterval from 'postgres-interval';
import { BasePostgreSqlPlatform, Utils } from '@mikro-orm/sql';
/** Platform implementation for PostgreSQL. */
export class PostgreSqlPlatform extends BasePostgreSqlPlatform {
convertIntervalToJSValue(value) {
return PostgresInterval(value);
}
convertIntervalToDatabaseValue(value) {
if (Utils.isObject(value) && 'toPostgres' in value && typeof value.toPostgres === 'function') {
return value.toPostgres();
}
return value;
}
unmarshallArray(value) {
return array.parse(value);
}
escape(value) {
if (typeof value === 'bigint') {
value = value.toString();
}
if (typeof value === 'string') {
return Client.prototype.escapeLiteral(value);
}
if (value instanceof Date) {
return `'${this.formatDate(value)}'`;
}
if (ArrayBuffer.isView(value)) {
return `E'\\\\x${value.toString('hex')}'`;
}
if (Array.isArray(value)) {
return value.map(v => this.escape(v)).join(', ');
}
return value;
}
/**
* @inheritDoc
*/
parseDate(value) {
// postgres-date returns `null` for a JS ISO string which has the `T` separator
if (typeof value === 'string' && value.charAt(10) === 'T') {
return new Date(value);
}
/* v8 ignore next */
if (typeof value === 'number') {
return new Date(value);
}
// @ts-ignore fix wrong type resolution during build
const parsed = parseDate(value);
/* v8 ignore next */
if (parsed === null) {
return value;
}
return parsed;
}
}

225
node_modules/@mikro-orm/postgresql/README.md generated vendored Normal file
View File

@@ -0,0 +1,225 @@
<h1 align="center">
<a href="https://mikro-orm.io"><img src="https://raw.githubusercontent.com/mikro-orm/mikro-orm/master/docs/static/img/logo-readme.svg?sanitize=true" alt="MikroORM" /></a>
</h1>
TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-orm.io/docs/unit-of-work/) and [Identity Map](https://mikro-orm.io/docs/identity-map/) patterns. Supports MongoDB, MySQL, MariaDB, PostgreSQL, SQLite (including libSQL), MSSQL and Oracle databases.
> Heavily inspired by [Doctrine](https://www.doctrine-project.org/) and [Hibernate](https://hibernate.org/).
[![NPM version](https://img.shields.io/npm/v/@mikro-orm/core.svg)](https://npmx.dev/package/@mikro-orm/core)
[![NPM dev version](https://img.shields.io/npm/v/@mikro-orm/core/next.svg)](https://npmx.dev/package/@mikro-orm/core)
[![Chat on discord](https://img.shields.io/discord/1214904142443839538?label=discord&color=blue)](https://discord.gg/w8bjxFHS7X)
[![Downloads](https://img.shields.io/npm/dm/@mikro-orm/core.svg)](https://npmx.dev/package/@mikro-orm/core)
[![Coverage Status](https://img.shields.io/coveralls/mikro-orm/mikro-orm.svg)](https://coveralls.io/r/mikro-orm/mikro-orm?branch=master)
[![Build Status](https://github.com/mikro-orm/mikro-orm/workflows/tests/badge.svg?branch=master)](https://github.com/mikro-orm/mikro-orm/actions?workflow=tests)
## Quick Start
Install a driver package for your database:
```sh
npm install @mikro-orm/postgresql # PostgreSQL
npm install @mikro-orm/mysql # MySQL
npm install @mikro-orm/mariadb # MariaDB
npm install @mikro-orm/sqlite # SQLite
npm install @mikro-orm/libsql # libSQL / Turso
npm install @mikro-orm/mongodb # MongoDB
npm install @mikro-orm/mssql # MS SQL Server
npm install @mikro-orm/oracledb # Oracle
```
> If you use additional packages like `@mikro-orm/cli`, `@mikro-orm/migrations`, or `@mikro-orm/entity-generator`, install `@mikro-orm/core` explicitly as well. See the [quick start guide](https://mikro-orm.io/docs/quick-start) for details.
### Define Entities
The recommended way to define entities is using [`defineEntity`](https://mikro-orm.io/docs/define-entity) with `setClass`:
```typescript
import { defineEntity, p, MikroORM } from '@mikro-orm/postgresql';
const AuthorSchema = defineEntity({
name: 'Author',
properties: {
id: p.integer().primary(),
name: p.string(),
email: p.string(),
born: p.datetime().nullable(),
books: () => p.oneToMany(Book).mappedBy('author'),
},
});
export class Author extends AuthorSchema.class {}
AuthorSchema.setClass(Author);
const BookSchema = defineEntity({
name: 'Book',
properties: {
id: p.integer().primary(),
title: p.string(),
author: () => p.manyToOne(Author).inversedBy('books'),
},
});
export class Book extends BookSchema.class {}
BookSchema.setClass(Book);
```
You can also define entities using [decorators](https://mikro-orm.io/docs/defining-entities) or [`EntitySchema`](https://mikro-orm.io/docs/entity-schema). See the [defining entities guide](https://mikro-orm.io/docs/defining-entities) for all options.
### Initialize and Use
```typescript
import { MikroORM, RequestContext } from '@mikro-orm/postgresql';
const orm = await MikroORM.init({
entities: [Author, Book],
dbName: 'my-db',
});
// Create new entities
const author = orm.em.create(Author, {
name: 'Jon Snow',
email: 'snow@wall.st',
});
const book = orm.em.create(Book, {
title: 'My Life on The Wall',
author,
});
// Flush persists all tracked changes in a single transaction
await orm.em.flush();
```
### Querying
```typescript
// Find with relations
const authors = await orm.em.findAll(Author, {
populate: ['books'],
orderBy: { name: 'asc' },
});
// Type-safe QueryBuilder
const qb = orm.em.createQueryBuilder(Author);
const result = await qb
.select('*')
.where({ books: { title: { $like: '%Wall%' } } })
.getResult();
```
### Request Context
In web applications, use `RequestContext` to isolate the identity map per request:
```typescript
const app = express();
app.use((req, res, next) => {
RequestContext.create(orm.em, next);
});
```
More info about `RequestContext` is described [here](https://mikro-orm.io/docs/identity-map/#request-context).
## Unit of Work
> Unit of Work maintains a list of objects (_entities_) affected by a business transaction
> and coordinates the writing out of changes. [(Martin Fowler)](https://www.martinfowler.com/eaaCatalog/unitOfWork.html)
When you call `em.flush()`, all computed changes are queried inside a database transaction. This means you can control transaction boundaries simply by making changes to your entities and calling `flush()` when ready.
```typescript
const author = await em.findOneOrFail(Author, 1, {
populate: ['books'],
});
author.name = 'Jon Snow II';
author.books.getItems().forEach(book => book.title += ' (2nd ed.)');
author.books.add(orm.em.create(Book, { title: 'New Book', author }));
// Flush computes change sets and executes them in a single transaction
await em.flush();
```
The above flush will execute:
```sql
begin;
update "author" set "name" = 'Jon Snow II' where "id" = 1;
update "book"
set "title" = case
when ("id" = 1) then 'My Life on The Wall (2nd ed.)'
when ("id" = 2) then 'Another Book (2nd ed.)'
else "title" end
where "id" in (1, 2);
insert into "book" ("title", "author_id") values ('New Book', 1);
commit;
```
## Core Features
- [Clean and Simple Entity Definition](https://mikro-orm.io/docs/defining-entities) — decorators, `EntitySchema`, or `defineEntity`
- [Identity Map](https://mikro-orm.io/docs/identity-map) and [Unit of Work](https://mikro-orm.io/docs/unit-of-work) — automatic change tracking
- [Entity References](https://mikro-orm.io/docs/entity-references) and [Collections](https://mikro-orm.io/docs/collections)
- [QueryBuilder](https://mikro-orm.io/docs/query-builder) and [Kysely Integration](https://mikro-orm.io/docs/kysely)
- [Transactions](https://mikro-orm.io/docs/transactions) and [Cascading](https://mikro-orm.io/docs/cascading)
- [Populating Relations](https://mikro-orm.io/docs/populating-relations) and [Loading Strategies](https://mikro-orm.io/docs/loading-strategies)
- [Filters](https://mikro-orm.io/docs/filters) and [Lifecycle Hooks](https://mikro-orm.io/docs/events#hooks)
- [Schema Generator](https://mikro-orm.io/docs/schema-generator) and [Migrations](https://mikro-orm.io/docs/migrations)
- [Entity Generator](https://mikro-orm.io/docs/entity-generator) and [Seeding](https://mikro-orm.io/docs/seeding)
- [Embeddables](https://mikro-orm.io/docs/embeddables), [Custom Types](https://mikro-orm.io/docs/custom-types), and [Serialization](https://mikro-orm.io/docs/serializing)
- [Composite and Foreign Keys as Primary Key](https://mikro-orm.io/docs/composite-keys)
- [Entity Constructors](https://mikro-orm.io/docs/entity-constructors) and [Property Validation](https://mikro-orm.io/docs/property-validation)
- [Modelling Relationships](https://mikro-orm.io/docs/relationships) and [Vanilla JS Support](https://mikro-orm.io/docs/usage-with-js)
## Documentation
MikroORM documentation, included in this repo in the root directory, is built with [Docusaurus](https://docusaurus.io) and publicly hosted on GitHub Pages at https://mikro-orm.io.
There is also auto-generated [CHANGELOG.md](CHANGELOG.md) file based on commit messages (via `semantic-release`).
## Example Integrations
You can find example integrations for some popular frameworks in the [`mikro-orm-examples` repository](https://github.com/mikro-orm/mikro-orm-examples):
### TypeScript Examples
- [Express + MongoDB](https://github.com/mikro-orm/express-ts-example-app)
- [Nest + MySQL](https://github.com/mikro-orm/nestjs-example-app)
- [RealWorld example app (Nest + MySQL)](https://github.com/mikro-orm/nestjs-realworld-example-app)
- [Koa + SQLite](https://github.com/mikro-orm/koa-ts-example-app)
- [GraphQL + PostgreSQL](https://github.com/driescroons/mikro-orm-graphql-example)
- [Inversify + PostgreSQL](https://github.com/PodaruDragos/inversify-example-app)
- [NextJS + MySQL](https://github.com/jonahallibone/mikro-orm-nextjs)
- [Accounts.js REST and GraphQL authentication + SQLite](https://github.com/darkbasic/mikro-orm-accounts-example)
- [Nest + Shopify + PostgreSQL + GraphQL](https://github.com/Cloudshelf/Shopify_CSConnector)
- [Elysia.js + libSQL + Bun](https://github.com/mikro-orm/elysia-bun-example-app)
- [Electron.js + PostgreSQL](https://github.com/adnanlah/electron-mikro-orm-example-app)
### JavaScript Examples
- [Express + SQLite](https://github.com/mikro-orm/express-js-example-app)
## Contributing
Contributions, issues and feature requests are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the process for submitting pull requests to us.
## Authors
**Martin Adámek**
- Twitter: [@B4nan](https://twitter.com/B4nan)
- Github: [@b4nan](https://github.com/b4nan)
See also the list of contributors who [participated](https://github.com/mikro-orm/mikro-orm/contributors) in this project.
## Show Your Support
Please star this repository if this project helped you!
> If you'd like to support my open-source work, consider sponsoring me directly at [github.com/sponsors/b4nan](https://github.com/sponsors/b4nan).
## License
Copyright © 2018-present [Martin Adámek](https://github.com/b4nan).
This project is licensed under the MIT License - see the [LICENSE file](LICENSE) for details.

11
node_modules/@mikro-orm/postgresql/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
export * from '@mikro-orm/sql';
export * from './PostgreSqlConnection.js';
export * from './PostgreSqlDriver.js';
export * from './PostgreSqlPlatform.js';
export { PostgreSqlEntityManager as EntityManager } from './PostgreSqlEntityManager.js';
export {
PostgreSqlMikroORM as MikroORM,
type PostgreSqlOptions as Options,
definePostgreSqlConfig as defineConfig,
} from './PostgreSqlMikroORM.js';
export { raw } from './raw.js';

7
node_modules/@mikro-orm/postgresql/index.js generated vendored Normal file
View File

@@ -0,0 +1,7 @@
export * from '@mikro-orm/sql';
export * from './PostgreSqlConnection.js';
export * from './PostgreSqlDriver.js';
export * from './PostgreSqlPlatform.js';
export { PostgreSqlEntityManager as EntityManager } from './PostgreSqlEntityManager.js';
export { PostgreSqlMikroORM as MikroORM, definePostgreSqlConfig as defineConfig } from './PostgreSqlMikroORM.js';
export { raw } from './raw.js';

View File

@@ -0,0 +1,4 @@
export function parse(source: string): string[];
export function parse<T>(source: string, transform: (value: string) => T): T[];

View File

@@ -0,0 +1,121 @@
'use strict'
const BACKSLASH = '\\'
const DQUOT = '"'
const LBRACE = '{'
const RBRACE = '}'
const LBRACKET = '['
const EQUALS = '='
const COMMA = ','
/** When the raw value is this, it means a literal `null` */
const NULL_STRING = 'NULL'
/**
* Parses an array according to
* https://www.postgresql.org/docs/17/arrays.html#ARRAYS-IO
*
* Trusts the data (mostly), so only hook up to trusted Postgres servers.
*/
function makeParseArrayWithTransform (transform) {
const haveTransform = transform != null
return function parseArray (str) {
const rbraceIndex = str.length - 1
if (rbraceIndex === 1) {
return []
}
if (str[rbraceIndex] !== RBRACE) {
throw new Error('Invalid array text - must end with }')
}
// If starts with `[`, it is specifying the index boundas. Skip past first `=`.
let position = 0
if (str[position] === LBRACKET) {
position = str.indexOf(EQUALS) + 1
}
if (str[position++] !== LBRACE) {
throw new Error('Invalid array text - must start with {')
}
const output = []
let current = output
const stack = []
let currentStringStart = position
let currentString = ''
let expectValue = true
for (; position < rbraceIndex; ++position) {
let char = str[position]
// > The array output routine will put double quotes around element values if
// > they are empty strings, contain curly braces, delimiter characters, double
// > quotes, backslashes, or white space, or match the word NULL. Double quotes
// > and backslashes embedded in element values will be backslash-escaped.
if (char === DQUOT) {
// It's escaped
currentStringStart = ++position
let dquot = str.indexOf(DQUOT, currentStringStart)
let backSlash = str.indexOf(BACKSLASH, currentStringStart)
while (backSlash !== -1 && backSlash < dquot) {
position = backSlash
const part = str.slice(currentStringStart, position)
currentString += part
currentStringStart = ++position
if (dquot === position++) {
// This was an escaped doublequote; find the next one!
dquot = str.indexOf(DQUOT, position)
}
// Either way, find the next backslash
backSlash = str.indexOf(BACKSLASH, position)
}
position = dquot
const part = str.slice(currentStringStart, position)
currentString += part
current.push(haveTransform ? transform(currentString) : currentString)
currentString = ''
expectValue = false
} else if (char === LBRACE) {
const newArray = []
current.push(newArray)
stack.push(current)
current = newArray
currentStringStart = position + 1
expectValue = true
} else if (char === COMMA) {
expectValue = true
} else if (char === RBRACE) {
expectValue = false
const arr = stack.pop()
if (arr === undefined) {
throw new Error("Invalid array text - too many '}'")
}
current = arr
} else if (expectValue) {
currentStringStart = position
while (
(char = str[position]) !== COMMA &&
char !== RBRACE &&
position < rbraceIndex
) {
++position
}
const part = str.slice(currentStringStart, position--)
current.push(
part === NULL_STRING ? null : haveTransform ? transform(part) : part
)
expectValue = false
} else {
throw new Error('Was expecting delimeter')
}
}
return output
}
}
const parseArray = makeParseArrayWithTransform()
exports.parse = (source, transform) =>
transform != null
? makeParseArrayWithTransform(transform)(source)
: parseArray(source)

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,35 @@
{
"name": "postgres-array",
"main": "index.js",
"version": "3.0.4",
"description": "Parse postgres array columns",
"license": "MIT",
"repository": "bendrucker/postgres-array",
"author": {
"name": "Ben Drucker",
"email": "bvdrucker@gmail.com",
"url": "bendrucker.me"
},
"engines": {
"node": ">=12"
},
"scripts": {
"test": "standard && tape test.js"
},
"types": "index.d.ts",
"keywords": [
"postgres",
"array",
"parser"
],
"dependencies": {},
"devDependencies": {
"standard": "^17.0.0",
"tape": "^5.0.0"
},
"files": [
"index.js",
"index.d.ts",
"readme.md"
]
}

View File

@@ -0,0 +1,43 @@
# postgres-array [![tests](https://github.com/bendrucker/postgres-array/workflows/tests/badge.svg)](https://github.com/bendrucker/postgres-array/actions?query=workflow%3Atests)
> Parse postgres array columns
## Install
```
npm install --save postgres-array
```
## Usage
```js
const { parse } = require('postgres-array')
parse('{1,2,3}', (value) => parseInt(value, 10))
//=> [1, 2, 3]
```
## API
#### `parse(input, [transform])` -> `array`
##### input
*Required*
Type: `string`
A Postgres array string.
##### transform
Type: `function`
Default: `identity`
A function that transforms non-null values inserted into the array.
## License
MIT © [Ben Drucker](http://bendrucker.me)

View File

@@ -0,0 +1,3 @@
declare function parseDate(isoDate: string): Date | number | null
declare function parseDate(isoDate: null | undefined): null
export default parseDate

View File

@@ -0,0 +1,308 @@
'use strict'
const CHAR_CODE_0 = '0'.charCodeAt(0)
const CHAR_CODE_9 = '9'.charCodeAt(0)
const CHAR_CODE_DASH = '-'.charCodeAt(0)
const CHAR_CODE_COLON = ':'.charCodeAt(0)
const CHAR_CODE_SPACE = ' '.charCodeAt(0)
const CHAR_CODE_DOT = '.'.charCodeAt(0)
const CHAR_CODE_Z = 'Z'.charCodeAt(0)
const CHAR_CODE_MINUS = '-'.charCodeAt(0)
const CHAR_CODE_PLUS = '+'.charCodeAt(0)
class PGDateParser {
constructor (dateString) {
this.dateString = dateString
this.pos = 0
this.stringLen = dateString.length
}
isDigit (c) {
return c >= CHAR_CODE_0 && c <= CHAR_CODE_9
}
/** read numbers and parse positive integer regex: \d+ */
readInteger () {
let val = 0
const start = this.pos
while (this.pos < this.stringLen) {
const chr = this.dateString.charCodeAt(this.pos)
if (this.isDigit(chr)) {
val = val * 10
this.pos += 1
val += chr - CHAR_CODE_0
} else {
break
}
}
if (start === this.pos) {
return null
}
return val
}
/** read exactly 2 numbers and parse positive integer. regex: \d{2} */
readInteger2 () {
const chr1 = this.dateString.charCodeAt(this.pos)
const chr2 = this.dateString.charCodeAt(this.pos + 1)
if (this.isDigit(chr1) && this.isDigit(chr2)) {
this.pos += 2
return (chr1 - CHAR_CODE_0) * 10 + (chr2 - CHAR_CODE_0)
}
return -1
}
skipChar (char) {
if (this.pos === this.stringLen) {
return false
}
if (this.dateString.charCodeAt(this.pos) === char) {
this.pos += 1
return true
}
return false
}
readBC () {
if (this.pos === this.stringLen) {
return false
}
if (this.dateString.slice(this.pos, this.pos + 3) === ' BC') {
this.pos += 3
return true
}
return false
}
checkEnd () {
return this.pos === this.stringLen
}
getUTC () {
return this.skipChar(CHAR_CODE_Z)
}
readSign () {
if (this.pos >= this.stringLen) {
return null
}
const char = this.dateString.charCodeAt(this.pos)
if (char === CHAR_CODE_PLUS) {
this.pos += 1
return 1
}
if (char === CHAR_CODE_MINUS) {
this.pos += 1
return -1
}
return null
}
getTZOffset () {
// special handling for '+00' at the end of - UTC
if (this.pos === this.stringLen - 3 && this.dateString.slice(this.pos, this.pos + 3) === '+00') {
this.pos += 3
return 0
}
if (this.stringLen === this.pos) {
return undefined
}
const sign = this.readSign()
if (sign === null) {
if (this.getUTC()) {
return 0
}
return undefined
}
const hours = this.readInteger2()
if (hours === null) {
return null
}
let offset = hours * 3600
if (!this.skipChar(CHAR_CODE_COLON)) {
return offset * sign * 1000
}
const minutes = this.readInteger2()
if (minutes === null) {
return null
}
offset += minutes * 60
if (!this.skipChar(CHAR_CODE_COLON)) {
return offset * sign * 1000
}
const seconds = this.readInteger2()
if (seconds == null) {
return null
}
return (offset + seconds) * sign * 1000
}
/* read milliseconds out of time fraction, returns 0 if missing, null if format invalid */
readMilliseconds () {
/* read milliseconds from fraction: .001=1, 0.1 = 100 */
if (this.skipChar(CHAR_CODE_DOT)) {
let i = 2
let val = 0
const start = this.pos
while (this.pos < this.stringLen) {
const chr = this.dateString.charCodeAt(this.pos)
if (this.isDigit(chr)) {
this.pos += 1
if (i >= 0) {
val += (chr - CHAR_CODE_0) * 10 ** i
}
i -= 1
} else {
break
}
}
if (start === this.pos) {
return null
}
return val
}
return 0
}
readDate () {
const year = this.readInteger()
if (!this.skipChar(CHAR_CODE_DASH)) {
return null
}
let month = this.readInteger2()
if (!this.skipChar(CHAR_CODE_DASH)) {
return null
}
const day = this.readInteger2()
if (year === null || month === null || day === null) {
return null
}
month = month - 1
return { year, month, day }
}
readTime () {
if (this.stringLen - this.pos < 9 || !this.skipChar(CHAR_CODE_SPACE)) {
return { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }
}
const hours = this.readInteger2()
if (hours === null || !this.skipChar(CHAR_CODE_COLON)) {
return null
}
const minutes = this.readInteger2()
if (minutes === null || !this.skipChar(CHAR_CODE_COLON)) {
return null
}
const seconds = this.readInteger2()
if (seconds === null) {
return null
}
const milliseconds = this.readMilliseconds()
if (milliseconds === null) {
return null
}
return { hours, minutes, seconds, milliseconds }
}
getJSDate () {
const date = this.readDate()
if (date === null) {
return null
}
const time = this.readTime()
if (time === null) {
return null
}
const tzOffset = this.getTZOffset()
if (tzOffset === null) {
return null
}
const isBC = this.readBC()
if (isBC) {
date.year = -(date.year - 1)
}
if (!this.checkEnd()) {
return null
}
let jsDate
if (tzOffset !== undefined) {
jsDate = new Date(
Date.UTC(date.year, date.month, date.day, time.hours, time.minutes, time.seconds, time.milliseconds)
)
if (date.year <= 99 && date.year >= -99) {
jsDate.setUTCFullYear(date.year)
}
if (tzOffset !== 0) {
jsDate.setTime(jsDate.getTime() - tzOffset)
}
} else {
jsDate = new Date(date.year, date.month, date.day, time.hours, time.minutes, time.seconds, time.milliseconds)
if (date.year <= 99 && date.year >= -99) {
jsDate.setFullYear(date.year)
}
}
return jsDate
}
static parse (dateString) {
return new PGDateParser(dateString).getJSDate()
}
}
module.exports = function parseDate (isoDate) {
if (isoDate === null || isoDate === undefined) {
return null
}
const date = PGDateParser.parse(isoDate)
// parsing failed, check for infinity
if (date === null) {
if (isoDate === 'infinity') {
return Infinity
}
if (isoDate === '-infinity') {
return -Infinity
}
}
return date
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,35 @@
{
"name": "postgres-date",
"main": "index.js",
"version": "2.1.0",
"description": "Postgres date column parser",
"license": "MIT",
"repository": "bendrucker/postgres-date",
"author": {
"name": "Ben Drucker",
"email": "bvdrucker@gmail.com",
"url": "bendrucker.me"
},
"engines": {
"node": ">=12"
},
"scripts": {
"test": "standard && tape test.js && tsd"
},
"keywords": [
"postgres",
"date",
"parser"
],
"dependencies": {},
"devDependencies": {
"standard": "^16.0.0",
"tape": "^5.0.0",
"tsd": "^0.19.0"
},
"files": [
"index.js",
"index.d.ts",
"readme.md"
]
}

View File

@@ -0,0 +1,48 @@
# postgres-date [![tests](https://github.com/bendrucker/postgres-date/workflows/tests/badge.svg)](https://github.com/bendrucker/postgres-date/actions?query=workflow%3Atests)
> Postgres date output parser
This package parses [date/time outputs](https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-DATETIME-OUTPUT) from Postgres into Javascript `Date` objects. Its goal is to match Postgres behavior and preserve data accuracy.
If you find a case where a valid Postgres output results in incorrect parsing (including loss of precision), please [create a pull request](https://github.com/bendrucker/postgres-date/compare) and provide a failing test.
**Supported Postgres Versions:** `>= 9.6`
All prior versions of Postgres are likely compatible but not officially supported.
## Install
```
npm install --save postgres-date
```
## Usage
```js
const parse = require('postgres-date')
parse('2011-01-23 22:15:51Z')
// => 2011-01-23T22:15:51.000Z
```
## API
#### `parse(isoDate)` -> `date`
##### isoDate
*Required*
Type: `string`
A date string from Postgres.
## Releases
The following semantic versioning increments will be used for changes:
* **Major**: Removal of support for Node.js versions or Postgres versions (not expected)
* **Minor**: Unused, since Postgres returns dates in standard ISO 8601 format
* **Patch**: Any fix for parsing behavior
## License
MIT © [Ben Drucker](http://bendrucker.me)

View File

@@ -0,0 +1,86 @@
declare namespace PostgresInterval {
export interface IPostgresInterval {
years: number;
months: number;
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
/**
* Returns an interval string. This allows the interval object to be passed into prepared statements.
*
* ```js
* var parse = require('postgres-interval')
* var interval = parse('01:02:03')
* // => { hours: 1, minutes: 2, seconds: 3 }
* interval.toPostgres()
* // 1 hour 2 minutes 3 seconds
* ```
*/
toPostgres(): string;
/**
* Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) compliant string, for example P0Y0M0DT0H9M0S.
*
* Also available as {@link toISOString toISOString}.
*
* ```js
* var parse = require('postgres-interval')
* var interval = parse('01:02:03')
* // => { hours: 1, minutes: 2, seconds: 3 }
* interval.toISO()
* // P0Y0M0DT1H2M3S
* ```
*/
toISO(): string;
/**
* Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) compliant string, for example P0Y0M0DT0H9M0S.
*
* Also available as {@link toISO toISO} for backwards compatibility.
*
* ```js
* var parse = require('postgres-interval')
* var interval = parse('01:02:03')
* // => { hours: 1, minutes: 2, seconds: 3 }
* interval.toISOString()
* // P0Y0M0DT1H2M3S
* ```
*/
toISOString(): string;
/**
* Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) compliant string shortened to minimum length, for example `PT9M`.
*
* ```js
* var parse = require('postgres-interval')
* var interval = parse('01:02:03')
* // => { hours: 1, minutes: 2, seconds: 3 }
* interval.toISOStringShort()
* // PT1H2M3S
* ```
*/
toISOStringShort(): string;
}
}
/**
* Parse Postgres interval columns.
*
* ```js
* var parse = require('postgres-interval')
* var interval = parse('01:02:03')
* // => { hours: 1, minutes: 2, seconds: 3 }
* interval.toPostgres()
* // 1 hour 2 minutes 3 seconds
* interval.toISOString()
* // P0Y0M0DT1H2M3S
* interval.toISOStringShort()
* // PT1H2M3S
* ```
*
* @param raw A Postgres interval string.
*/
declare function PostgresInterval(raw: string): PostgresInterval.IPostgresInterval;
export = PostgresInterval;

View File

@@ -0,0 +1,266 @@
'use strict'
module.exports = PostgresInterval
function PostgresInterval (raw) {
if (!(this instanceof PostgresInterval)) {
return new PostgresInterval(raw)
}
this.years = 0
this.months = 0
this.days = 0
this.hours = 0
this.minutes = 0
this.seconds = 0
this.milliseconds = 0
parse(this, raw)
}
PostgresInterval.prototype.toPostgres = function () {
let postgresString = ''
if (this.years) {
postgresString += this.years === 1 ? this.years + ' year' : this.years + ' years'
}
if (this.months) {
if (postgresString.length) {
postgresString += ' '
}
postgresString += this.months === 1 ? this.months + ' month' : this.months + ' months'
}
if (this.days) {
if (postgresString.length) {
postgresString += ' '
}
postgresString += this.days === 1 ? this.days + ' day' : this.days + ' days'
}
if (this.hours) {
if (postgresString.length) {
postgresString += ' '
}
postgresString += this.hours === 1 ? this.hours + ' hour' : this.hours + ' hours'
}
if (this.minutes) {
if (postgresString.length) {
postgresString += ' '
}
postgresString += this.minutes === 1 ? this.minutes + ' minute' : this.minutes + ' minutes'
}
if (this.seconds || this.milliseconds) {
if (postgresString.length) {
postgresString += ' '
}
if (this.milliseconds) {
const value = Math.trunc((this.seconds + this.milliseconds / 1000) * 1000000) / 1000000
postgresString += value === 1 ? value + ' second' : value + ' seconds'
} else {
postgresString += this.seconds === 1 ? this.seconds + ' second' : this.seconds + ' seconds'
}
}
return postgresString === '' ? '0' : postgresString
}
const propertiesISOEquivalent = {
years: 'Y',
months: 'M',
days: 'D',
hours: 'H',
minutes: 'M',
seconds: 'S'
}
// according to ISO 8601
PostgresInterval.prototype.toISOString = PostgresInterval.prototype.toISO =
function () {
return toISOString.call(this, { short: false })
}
PostgresInterval.prototype.toISOStringShort = function () {
return toISOString.call(this, { short: true })
}
function toISOString ({ short }) {
let datePart = ''
if (!short || this.years) {
datePart += this.years + propertiesISOEquivalent.years
}
if (!short || this.months) {
datePart += this.months + propertiesISOEquivalent.months
}
if (!short || this.days) {
datePart += this.days + propertiesISOEquivalent.days
}
let timePart = ''
if (!short || this.hours) {
timePart += this.hours + propertiesISOEquivalent.hours
}
if (!short || this.minutes) {
timePart += this.minutes + propertiesISOEquivalent.minutes
}
if (!short || (this.seconds || this.milliseconds)) {
if (this.milliseconds) {
timePart += (Math.trunc((this.seconds + this.milliseconds / 1000) * 1000000) / 1000000) + propertiesISOEquivalent.seconds
} else {
timePart += this.seconds + propertiesISOEquivalent.seconds
}
}
if (!timePart && !datePart) {
return 'PT0S'
}
if (!timePart) {
return `P${datePart}`
}
return `P${datePart}T${timePart}`
}
const position = { value: 0 }
function readNextNum (interval) {
let val = 0
while (position.value < interval.length) {
const char = interval[position.value]
if (char >= '0' && char <= '9') {
val = val * 10 + +char
position.value++
} else {
break
}
}
return val
}
function parseMillisecond (interval) {
const previousPosition = position.value
const currentValue = readNextNum(interval)
const valueStringLength = position.value - previousPosition
switch (valueStringLength) {
case 1:
return currentValue * 100
case 2:
return currentValue * 10
case 3:
return currentValue
case 4:
return currentValue / 10
case 5:
return currentValue / 100
case 6:
return currentValue / 1000
}
// slow path
const remainder = valueStringLength - 3
return currentValue / Math.pow(10, remainder)
}
function parse (instance, interval) {
if (!interval) {
return
}
position.value = 0
let currentValue
let nextNegative = 1
while (position.value < interval.length) {
const char = interval[position.value]
if (char === '-') {
nextNegative = -1
position.value++
continue
} else if (char === '+') {
position.value++
continue
} else if (char === ' ') {
position.value++
continue
} else if (char < '0' || char > '9') {
position.value++
continue
} else {
currentValue = readNextNum(interval)
if (interval[position.value] === ':') {
instance.hours = currentValue ? nextNegative * currentValue : 0
position.value++
currentValue = readNextNum(interval)
instance.minutes = currentValue ? nextNegative * currentValue : 0
position.value++
currentValue = readNextNum(interval)
instance.seconds = currentValue ? nextNegative * currentValue : 0
if (interval[position.value] === '.') {
position.value++
currentValue = parseMillisecond(interval)
instance.milliseconds = currentValue ? nextNegative * currentValue : 0
}
return
}
// skip space
position.value++
const unit = interval[position.value]
if (unit === 'y') {
instance.years = currentValue ? nextNegative * currentValue : 0
} else if (unit === 'm') {
instance.months = currentValue ? nextNegative * currentValue : 0
} else if (unit === 'd') {
instance.days = currentValue ? nextNegative * currentValue : 0
}
nextNegative = 1
}
}
}
PostgresInterval.parse = function (interval) {
const instance = {
years: 0,
months: 0,
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
milliseconds: 0
}
parse(instance, interval)
return instance
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Ben Drucker <bvdrucker@gmail.com> (bendrucker.me)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,34 @@
{
"name": "postgres-interval",
"main": "index.js",
"version": "4.0.2",
"description": "Parse Postgres interval columns",
"license": "MIT",
"repository": "bendrucker/postgres-interval",
"author": {
"name": "Ben Drucker",
"email": "bvdrucker@gmail.com",
"url": "https://www.bendrucker.me"
},
"engines": {
"node": ">=12"
},
"scripts": {
"test": "standard && tape test.js"
},
"keywords": [
"postgres",
"interval",
"parser"
],
"dependencies": {},
"devDependencies": {
"standard": "^17.0.0",
"tape": "^5.0.0"
},
"files": [
"index.js",
"index.d.ts",
"readme.md"
]
}

View File

@@ -0,0 +1,62 @@
# postgres-interval [![tests](https://github.com/bendrucker/postgres-interval/workflows/tests/badge.svg)](https://github.com/bendrucker/postgres-interval/actions?query=workflow%3Atests)
> Parse Postgres interval columns
## Install
```sh
npm install --save postgres-interval
```
## Usage
```js
var parse = require('postgres-interval')
var interval = parse('01:02:03')
// => { hours: 1, minutes: 2, seconds: 3 }
interval.toPostgres()
// 1 hour 2 minutes 3 seconds
interval.toISOString()
// P0Y0M0DT1H2M3S
interval.toISOStringShort()
// PT1H2M3S
```
This package parses the default Postgres interval style. If you have changed [`intervalstyle`](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-INTERVALSTYLE), you will need to set it back to the default:
```sql
set intervalstyle to default;
```
## API
#### `parse(pgInterval)` -> `interval`
##### pgInterval
*Required*
Type: `string`
A Postgres interval string.
This package is focused on parsing Postgres outputs. It optimizes for performance by assuming that inputs follow the default interval format. It does not perform any validation on the input. If any interval field is not found, its value will be set to `0` in the returned `interval`.
#### `interval.toPostgres()` -> `string`
Returns an interval string. This allows the interval object to be passed into prepared statements.
#### `interval.toISOString()` -> `string`
Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) compliant string, for example `P0Y0M0DT0H9M0S`.
Also available as `interval.toISO()` for backwards compatibility.
#### `interval.toISOStringShort()` -> `string`
Returns an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) compliant string shortened to minimum length, for example `PT9M`.
## License
MIT © [Ben Drucker](http://bendrucker.me)

67
node_modules/@mikro-orm/postgresql/package.json generated vendored Normal file
View File

@@ -0,0 +1,67 @@
{
"name": "@mikro-orm/postgresql",
"version": "7.0.2",
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
"keywords": [
"data-mapper",
"ddd",
"entity",
"identity-map",
"javascript",
"js",
"mariadb",
"mikro-orm",
"mongo",
"mongodb",
"mysql",
"orm",
"postgresql",
"sqlite",
"sqlite3",
"ts",
"typescript",
"unit-of-work"
],
"homepage": "https://mikro-orm.io",
"bugs": {
"url": "https://github.com/mikro-orm/mikro-orm/issues"
},
"license": "MIT",
"author": "Martin Adámek",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/mikro-orm/mikro-orm.git"
},
"type": "module",
"exports": {
"./package.json": "./package.json",
".": "./index.js"
},
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "yarn compile && yarn copy",
"clean": "yarn run -T rimraf ./dist",
"compile": "yarn run -T tsc -p tsconfig.build.json",
"copy": "node ../../scripts/copy.mjs"
},
"dependencies": {
"@mikro-orm/sql": "7.0.2",
"kysely": "0.28.12",
"pg": "8.20.0",
"pg-cursor": "2.19.0",
"postgres-array": "3.0.4",
"postgres-date": "2.1.0",
"postgres-interval": "4.0.2"
},
"devDependencies": {
"@mikro-orm/core": "^7.0.2"
},
"peerDependencies": {
"@mikro-orm/core": "7.0.2"
},
"engines": {
"node": ">= 22.17.0"
}
}

77
node_modules/@mikro-orm/postgresql/raw.d.ts generated vendored Normal file
View File

@@ -0,0 +1,77 @@
import { type AnyString, type Dictionary, type EntityKey, type RawQueryFragment } from '@mikro-orm/sql';
import type { SelectQueryBuilder as KyselySelectQueryBuilder } from 'kysely';
/** @internal Type for QueryBuilder instances passed to raw() - uses toRaw to distinguish from Kysely QueryBuilder */
type QueryBuilderLike = {
toQuery(): {
sql: string;
params: readonly unknown[];
};
toRaw(): RawQueryFragment;
};
/**
* Creates raw SQL query fragment that can be assigned to a property or part of a filter. This fragment is represented
* by `RawQueryFragment` class instance that can be serialized to a string, so it can be used both as an object value
* and key. When serialized, the fragment key gets cached and only such cached key will be recognized by the ORM.
* This adds a runtime safety to the raw query fragments.
*
* > **`raw()` helper is required since v6 to use a raw fragment in your query, both through EntityManager and QueryBuilder.**
*
* ```ts
* // as a value
* await em.find(User, { time: raw('now()') });
*
* // as a key
* await em.find(User, { [raw('lower(name)')]: name.toLowerCase() });
*
* // value can be empty array
* await em.find(User, { [raw('(select 1 = 1)')]: [] });
* ```
*
* The `raw` helper supports several signatures, you can pass in a callback that receives the current property alias:
*
* ```ts
* await em.find(User, { [raw(alias => `lower(${alias}.name)`)]: name.toLowerCase() });
* ```
*
* You can also use the `sql` tagged template function, which works the same, but supports only the simple string signature:
*
* ```ts
* await em.find(User, { [sql`lower(name)`]: name.toLowerCase() });
* ```
*
* When using inside filters, you might have to use a callback signature to create new raw instance for every filter usage.
*
* ```ts
* @Filter({ name: 'long', cond: () => ({ [raw('length(perex)')]: { $gt: 10000 } }) })
* ```
*
* The `raw` helper can be used within indexes and uniques to write database-agnostic SQL expressions. In that case, you can use `'??'` to tag your database identifiers (table name, column names, index name, ...) inside your expression, and pass those identifiers as a second parameter to the `raw` helper. Internally, those will automatically be quoted according to the database in use:
*
* ```ts
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("country")
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`country`)
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => raw(`create index ?? on ?? (??)`, ['custom_idx_on_name', table, columns.name]) })
* @Entity({ schema: 'library' })
* export class Author { ... }
* ```
*
* You can also use the `quote` tag function to write database-agnostic SQL expressions. The end-result is the same as using the `raw` function regarding database identifiers quoting, only to have a more elegant expression syntax:
*
* ```ts
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
* @Entity({ schema: 'library' })
* export class Author { ... }
* ```
*/
export declare function raw<R = RawQueryFragment & symbol, T extends object = any>(
sql:
| QueryBuilderLike
| KyselySelectQueryBuilder<any, any, any>
| EntityKey<T>
| EntityKey<T>[]
| AnyString
| ((alias: string) => string)
| RawQueryFragment,
params?: readonly unknown[] | Dictionary<unknown>,
): R;
export {};

64
node_modules/@mikro-orm/postgresql/raw.js generated vendored Normal file
View File

@@ -0,0 +1,64 @@
import { raw as raw_, Utils } from '@mikro-orm/sql';
/**
* Creates raw SQL query fragment that can be assigned to a property or part of a filter. This fragment is represented
* by `RawQueryFragment` class instance that can be serialized to a string, so it can be used both as an object value
* and key. When serialized, the fragment key gets cached and only such cached key will be recognized by the ORM.
* This adds a runtime safety to the raw query fragments.
*
* > **`raw()` helper is required since v6 to use a raw fragment in your query, both through EntityManager and QueryBuilder.**
*
* ```ts
* // as a value
* await em.find(User, { time: raw('now()') });
*
* // as a key
* await em.find(User, { [raw('lower(name)')]: name.toLowerCase() });
*
* // value can be empty array
* await em.find(User, { [raw('(select 1 = 1)')]: [] });
* ```
*
* The `raw` helper supports several signatures, you can pass in a callback that receives the current property alias:
*
* ```ts
* await em.find(User, { [raw(alias => `lower(${alias}.name)`)]: name.toLowerCase() });
* ```
*
* You can also use the `sql` tagged template function, which works the same, but supports only the simple string signature:
*
* ```ts
* await em.find(User, { [sql`lower(name)`]: name.toLowerCase() });
* ```
*
* When using inside filters, you might have to use a callback signature to create new raw instance for every filter usage.
*
* ```ts
* @Filter({ name: 'long', cond: () => ({ [raw('length(perex)')]: { $gt: 10000 } }) })
* ```
*
* The `raw` helper can be used within indexes and uniques to write database-agnostic SQL expressions. In that case, you can use `'??'` to tag your database identifiers (table name, column names, index name, ...) inside your expression, and pass those identifiers as a second parameter to the `raw` helper. Internally, those will automatically be quoted according to the database in use:
*
* ```ts
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("country")
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`country`)
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => raw(`create index ?? on ?? (??)`, ['custom_idx_on_name', table, columns.name]) })
* @Entity({ schema: 'library' })
* export class Author { ... }
* ```
*
* You can also use the `quote` tag function to write database-agnostic SQL expressions. The end-result is the same as using the `raw` function regarding database identifiers quoting, only to have a more elegant expression syntax:
*
* ```ts
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
* @Entity({ schema: 'library' })
* export class Author { ... }
* ```
*/
export function raw(sql, params) {
if (Utils.isObject(sql) && 'compile' in sql) {
const query = sql.compile();
const processed = query.sql.replaceAll(/\$\d+/g, '?');
return raw_(processed, query.parameters);
}
return raw_(sql, params);
}