-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ca38177
Showing
120 changed files
with
5,348 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# dependencies | ||
node_modules | ||
package-lock.json | ||
|
||
|
||
# misc | ||
.DS_Store | ||
.env* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"tabWidth": 2, | ||
"printWidth": 80, | ||
"endOfLine": "auto", | ||
"singleQuote": true, | ||
"arrowParens": "avoid", | ||
"trailingComma": "es5", | ||
"bracketSameLine": true | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { presets } from '#env'; | ||
import { migrate } from '#db/migrate/run.js'; | ||
|
||
await migrate({ | ||
...presets.migrate, | ||
command: process.argv[2] ?? 'up', | ||
options: process.argv.slice(3), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { copyFileSync } from 'fs'; | ||
import { resolve as resolvePath } from 'path'; | ||
|
||
import { presets } from '#env'; | ||
import { CWD, resolve } from '#utils/location.js'; | ||
|
||
if (!presets.app.isProduction) { | ||
const source = resolve(import.meta, '../src/utils/pre-push'); | ||
const target = resolvePath(CWD, '.git/hooks/pre-push'); | ||
|
||
copyFileSync(source, target); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { runAllTestFiles, printAllTestTree } from '#test/run.js'; | ||
|
||
process.argv[2] === 'status' | ||
? await printAllTestTree() | ||
: await runAllTestFiles(); |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "@uah/server", | ||
"private": true, | ||
"author": "UAH", | ||
"description": "description", | ||
"version": "1.0.0", | ||
"license": "ISC", | ||
"type": "module", | ||
"typings": "index.d.ts", | ||
"engines": { | ||
"node": ">=20.1.0" | ||
}, | ||
"imports": { | ||
"#runtime/*": "./src/runtime/*", | ||
"#compiler/*": "./src/compiler/*" | ||
}, | ||
"dependencies": { | ||
"typescript": "next", | ||
"uWebSockets.js": "uNetworking/uWebSockets.js#v20.30.0" | ||
}, | ||
"devDependencies": { | ||
"@typescript-eslint/eslint-plugin": "latest", | ||
"@typescript-eslint/parser": "latest", | ||
"eslint": "latest", | ||
"eslint-config-prettier": "latest", | ||
"eslint-plugin-prettier": "latest", | ||
"prettier": "latest" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import process from 'process'; | ||
import { pathToFileURL } from 'url'; | ||
|
||
export const CWD = process.cwd(); | ||
export const CWD_URL = pathToFileURL(CWD).href; | ||
|
||
export const LIB_NAME = '@uah/server'; | ||
|
||
export const SERVER = { | ||
host: 'localhost', | ||
port: 80, | ||
path: '/', | ||
url: 'http://localhost/', | ||
origin: 'http://localhost', | ||
|
||
instance: null, | ||
secure: false, | ||
|
||
set(config) { | ||
const url = new URL(config.url); | ||
|
||
this.url = url.href; | ||
this.host = url.hostname; | ||
this.path = url.pathname; | ||
this.origin = url.origin; | ||
|
||
this.secure = url.protocol === 'https:'; | ||
this.port = url.port ? +url.port : this.secure ? 443 : 80; | ||
|
||
if (config.proxy) { | ||
this.proxy = config.proxy; | ||
} | ||
}, | ||
}; | ||
|
||
export function initConfig({ pathsBasePath, plugins }) { | ||
const config = plugins?.find(({ name }) => name === LIB_NAME); | ||
|
||
if (config?.server) { | ||
SERVER.set(config.server); | ||
} | ||
|
||
if (config?.bundle) { | ||
BUNDLE.set(config.bundle); | ||
} | ||
|
||
LOCATION.root.url = SERVER.path; | ||
LOCATION.root.path = pathsBasePath + '/'; | ||
|
||
LOCATION.src.url = LOCATION.root.url + BUNDLE.source + '/'; | ||
LOCATION.src.path = LOCATION.root.path + LOCATION.src.name + '/'; | ||
|
||
LOCATION.app.url = LOCATION.src.url + LOCATION.app.name + '/'; | ||
LOCATION.app.path = LOCATION.src.path + LOCATION.app.name + '/'; | ||
|
||
LOCATION.lib.url = LOCATION.src.url + LOCATION.lib.name + '/'; | ||
LOCATION.lib.path = LOCATION.src.path + LOCATION.lib.name + '/'; | ||
|
||
LOCATION.dev.url = LOCATION.src.url + LOCATION.dev.name + '/'; | ||
|
||
LOCATION.assets.url = LOCATION.src.url + LOCATION.assets.name + '/'; | ||
LOCATION.assets.path = LOCATION.src.path + LOCATION.assets.name + '/'; | ||
|
||
LOCATION.runtime.url = LOCATION.src.url; | ||
LOCATION.runtime.path = | ||
LOCATION.root.path + 'node_modules/' + LIB_NAME + '/src/runtime/'; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { startServer } from './server/app.js'; | ||
|
||
export const app = { | ||
server: { | ||
run: startServer, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { fs } from '../utils/native.js'; | ||
import { CWD } from '../utils/location.js'; | ||
|
||
const mapVars = Object.assign(Object.create(null), { | ||
_uid: context => context.uid, | ||
_lang: context => context.language, | ||
}); | ||
|
||
const getValues = (context, payload, params) => { | ||
const values = []; | ||
|
||
for (let i = 0; i < params.length; i++) { | ||
const name = params[i]; | ||
values[i] = mapVars[name]?.(context) ?? payload[name]; | ||
} | ||
|
||
return values; | ||
}; | ||
|
||
export const createAction = | ||
({ text, params, returnMethod }) => | ||
async (context, payload) => | ||
returnMethod( | ||
await context.db.unsafe(text, getValues(context, payload, params)) | ||
); | ||
|
||
export const createActionFromFileSQL = ({ path: names }) => { | ||
let action = async (context, payload) => { | ||
const name = `${names[0]}/${names[1]}/${names[2]}`; | ||
const path = `${CWD}/src/app/${names[0]}/${names[1]}/sql/${names[2]}.sql`; | ||
|
||
const params = []; | ||
const source = (await fs.readFile(path, 'utf8')).split('${'); | ||
|
||
for (let i = 1; i < source.length; i++) { | ||
const sql = source[i]; | ||
const index = sql.indexOf('}'); | ||
|
||
const key = sql.slice(0, index).trim(); | ||
const num = params.includes(key) | ||
? params.indexOf(key) + 1 | ||
: params.push(key); | ||
|
||
source[i] = '$' + num + sql.slice(index + 1); | ||
} | ||
|
||
action = createAction({ | ||
name, | ||
params, | ||
text: source.join(''), | ||
returnMethod: res => res.rows, | ||
}); | ||
|
||
return await action(context, payload); | ||
}; | ||
|
||
return (context, payload) => action(context, payload); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import postgres from 'postgres'; | ||
import { presets } from '#env'; | ||
import { noop } from '#utils/native.js'; | ||
import { onAborted } from '#utils/process.js'; | ||
|
||
export const getConnectOptions = ( | ||
options = presets.db, | ||
ns = presets.app.id.toUpperCase() | ||
) => { | ||
options = { | ||
onnotice: noop, | ||
connect_timeout: 60, | ||
...options, | ||
connection: { | ||
application_name: presets.app.id, | ||
...options?.connection, | ||
}, | ||
}; | ||
|
||
const { env } = process; | ||
|
||
if (env[ns + '_DB_USER']) options.username = env[ns + '_DB_USER']; | ||
if (env[ns + '_DB_PASS']) options.password = env[ns + '_DB_PASS']; | ||
|
||
if (env.DB_PORT) options.port = env.DB_PORT; | ||
if (env.DB_HOST) options.host = env.DB_HOST; | ||
if (env.DB_NAME) options.database = env.DB_NAME; | ||
|
||
return options; | ||
}; | ||
|
||
export const createClient = (options = getConnectOptions()) => { | ||
const client = postgres(options); | ||
|
||
onAborted(() => client.end({ timeout: 0 })); | ||
|
||
return client; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
export const CODES = { | ||
INVALID_TEXT_REPRESENTATION: '22P02', | ||
INTEGRITY_CONSTRAINT_VIOLATION: '23000', | ||
RESTRICT_VIOLATION: '23001', | ||
NOT_NULL_VIOLATION: '23502', | ||
FOREIGN_KEY_VIOLATION: '23503', | ||
UNIQUE_VIOLATION: '23505', | ||
CHECK_VIOLATION: '23514', | ||
EXCLUSION_VIOLATION: '23P01', | ||
INSUFFICIENT_PRIVILEGE: '42501', | ||
INVALID_DATETIME_FORMAT: '22007', | ||
DATETIME_FIELD_OVERFLOW: '22008', | ||
INVALID_BINARY_REPRESENTATION: '22P03', | ||
NUMERIC_VALUE_OUT_OF_RANGE: '22003', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { presets } from '#env'; | ||
import { quoteLiteral } from './utils/text.js'; | ||
import { createClient } from './client.js'; | ||
import { factory } from './sql/query.js'; | ||
|
||
const DB_POOL = Symbol('DB POOL'); | ||
|
||
function setCustomParams({ db, uid, route, service }, params) { | ||
let sql = 'SET LOCAL "custom.app"=' + quoteLiteral(presets.app.id); | ||
|
||
if (uid) { | ||
sql += ';SET LOCAL "custom.uid"=' + quoteLiteral(uid); | ||
} | ||
|
||
if (route?.name) { | ||
sql += ';SET LOCAL "custom.action"=' + quoteLiteral(route.name); | ||
} else if (service?.name) { | ||
sql += ';SET LOCAL "custom.action"=' + quoteLiteral(service.name); | ||
} | ||
|
||
if (params) { | ||
for (const key of Object.keys(params)) { | ||
const value = params[key]; | ||
if (value != null) { | ||
sql += `;SET LOCAL "custom.${key}"=`; | ||
sql += | ||
value === true | ||
? "'t'" | ||
: value === false | ||
? "'f'" | ||
: quoteLiteral(value); | ||
} | ||
} | ||
} | ||
|
||
return db.unsafe(sql); | ||
} | ||
|
||
async function transaction(action, payload, params) { | ||
if (this[DB_POOL]) { | ||
return await this.db.savepoint(async () => { | ||
await setCustomParams(this, params?.custom); | ||
return await action(this, payload); | ||
}); | ||
} | ||
|
||
this[DB_POOL] = this.db; | ||
|
||
try { | ||
return await this.db.begin(async db => { | ||
this.db = db; | ||
await setCustomParams(this, params?.custom); | ||
return await action(this, payload); | ||
}); | ||
} finally { | ||
this.db = this[DB_POOL]; | ||
this[DB_POOL] = null; | ||
|
||
if (this.transactionTasks) { | ||
for (const action of this.transactionTasks) | ||
await action(this).catch(console.error); | ||
this.transactionTasks.clear(); | ||
} | ||
} | ||
} | ||
|
||
function isTransaction() { | ||
return !!this[DB_POOL]; | ||
} | ||
|
||
async function runAfterTransaction(action) { | ||
(this.transactionTasks ??= new Set()).add(action); | ||
} | ||
|
||
export const setDataBaseContext = (context, options) => { | ||
context[DB_POOL] = null; | ||
context.transaction = transaction; | ||
context.transactionTasks = null; | ||
context.isTransaction = isTransaction; | ||
context.runAfterTransaction = runAfterTransaction; | ||
context.db = createClient(options); | ||
context.sql = factory(context); | ||
}; |
Oops, something went wrong.