schematic-pg 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/auth/policy-types.d.ts +6 -0
- package/dist/api/auth/policy-types.js +1 -0
- package/dist/api/auth/policy.d.ts +3 -1
- package/dist/api/auth/policy.js +11 -8
- package/dist/api/middleware/db.d.ts +3 -3
- package/dist/api/middleware/db.js +3 -5
- package/dist/api-generator/app-generator.js +6 -1
- package/dist/api-generator/policy-generator.js +2 -7
- package/dist/cli/templates.js +0 -4
- package/package.json +2 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { WhereInput } from '../../db/where-translator.js';
|
|
2
|
-
import {
|
|
2
|
+
import type { NormalizedPolicy, PolicyOperation } from './policy-types.js';
|
|
3
3
|
import type { AuthContext } from './types.js';
|
|
4
|
+
export type { NormalizedPolicy, PolicyOperation } from './policy-types.js';
|
|
4
5
|
export { ForbiddenError, UnauthorizedError } from './errors.js';
|
|
6
|
+
export declare function configurePolicies(next: Record<string, NormalizedPolicy[]>): void;
|
|
5
7
|
export declare function assertPolicy(model: string, role: string, operation: PolicyOperation): NormalizedPolicy;
|
|
6
8
|
export declare function resolvePolicyWhere(policy: NormalizedPolicy, auth: AuthContext): WhereInput | undefined;
|
|
7
9
|
export declare function mergeWhere(primary: Record<string, unknown>, policyWhere?: WhereInput): Record<string, unknown>;
|
package/dist/api/auth/policy.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import { POLICIES } from 'generated/policies.js';
|
|
2
1
|
import { ForbiddenError } from './errors.js';
|
|
3
2
|
import { interpolateTemplate } from './template.js';
|
|
4
3
|
import { PUBLIC_ROLE } from './types.js';
|
|
5
|
-
const SIMPLE_WHERE_PATTERN = /^(\w+)\s*(=|!=|<>|>=|<=|>|<)\s*(.+)$/;
|
|
6
4
|
export { ForbiddenError, UnauthorizedError } from './errors.js';
|
|
5
|
+
const SIMPLE_WHERE_PATTERN = /^(\w+)\s*(=|!=|<>|>=|<=|>|<)\s*(.+)$/;
|
|
6
|
+
let policies = {};
|
|
7
|
+
export function configurePolicies(next) {
|
|
8
|
+
policies = next;
|
|
9
|
+
}
|
|
7
10
|
export function assertPolicy(model, role, operation) {
|
|
8
|
-
const
|
|
9
|
-
if (!
|
|
11
|
+
const modelPolicies = policies[model];
|
|
12
|
+
if (!modelPolicies || modelPolicies.length === 0) {
|
|
10
13
|
throw new ForbiddenError(`No policies configured for model "${model}"`);
|
|
11
14
|
}
|
|
12
|
-
const policy = findPolicyForRole(
|
|
15
|
+
const policy = findPolicyForRole(modelPolicies, role);
|
|
13
16
|
if (!policy) {
|
|
14
17
|
throw new ForbiddenError(`Role "${role}" is not allowed to ${operation} ${model}`);
|
|
15
18
|
}
|
|
@@ -34,13 +37,13 @@ export function mergeWhere(primary, policyWhere) {
|
|
|
34
37
|
}
|
|
35
38
|
return { AND: [primary, policyWhere] };
|
|
36
39
|
}
|
|
37
|
-
function findPolicyForRole(
|
|
38
|
-
const directMatch =
|
|
40
|
+
function findPolicyForRole(modelPolicies, role) {
|
|
41
|
+
const directMatch = modelPolicies.find((policy) => policy.role === role);
|
|
39
42
|
if (directMatch) {
|
|
40
43
|
return directMatch;
|
|
41
44
|
}
|
|
42
45
|
if (role !== PUBLIC_ROLE) {
|
|
43
|
-
return
|
|
46
|
+
return modelPolicies.find((policy) => policy.role === PUBLIC_ROLE);
|
|
44
47
|
}
|
|
45
48
|
return undefined;
|
|
46
49
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Pool } from 'pg';
|
|
2
2
|
import type { MiddlewareHandler } from 'hono';
|
|
3
|
-
import type { DbClient } from 'generated
|
|
3
|
+
import type { DbClient } from '../../types/generated-db.stub.js';
|
|
4
4
|
import type { AppEnv } from '../types.js';
|
|
5
|
-
export declare
|
|
6
|
-
export declare function createDbMiddleware(options?: {
|
|
5
|
+
export declare function createDbMiddleware(options: {
|
|
7
6
|
pool?: Pool;
|
|
7
|
+
createDbClient: (pool: Pool) => DbClient;
|
|
8
8
|
}): MiddlewareHandler<AppEnv>;
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { Pool } from 'pg';
|
|
2
|
-
import { createDbClient } from 'generated/db.js';
|
|
3
2
|
import { getDatabaseUrl } from '../../db/config.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const client = options.pool ? createDbClient(options.pool) : db;
|
|
3
|
+
export function createDbMiddleware(options) {
|
|
4
|
+
const pool = options.pool ?? new Pool({ connectionString: getDatabaseUrl() });
|
|
5
|
+
const client = options.createDbClient(pool);
|
|
8
6
|
return async (c, next) => {
|
|
9
7
|
c.set('db', client);
|
|
10
8
|
await next();
|
|
@@ -37,6 +37,9 @@ export class AppGenerator {
|
|
|
37
37
|
"import { prettyJSON } from 'hono/pretty-json';",
|
|
38
38
|
"import { serve } from '@hono/node-server';",
|
|
39
39
|
routeImports,
|
|
40
|
+
"import { createDbClient } from './db.js';",
|
|
41
|
+
"import { POLICIES } from './policies.js';",
|
|
42
|
+
`import { configurePolicies } from '${PACKAGE_NAME}/api/auth/policy';`,
|
|
40
43
|
`import { createAuthMiddleware } from '${PACKAGE_NAME}/api/auth/middleware';`,
|
|
41
44
|
`import { createJwtResolver } from '${PACKAGE_NAME}/api/auth/jwt-resolver';`,
|
|
42
45
|
`import type { AuthResolver } from '${PACKAGE_NAME}/api/auth/types';`,
|
|
@@ -44,6 +47,8 @@ export class AppGenerator {
|
|
|
44
47
|
`import { handleError } from '${PACKAGE_NAME}/api/middleware/errors';`,
|
|
45
48
|
`import type { AppEnv } from '${PACKAGE_NAME}/api/types';`,
|
|
46
49
|
'',
|
|
50
|
+
'configurePolicies(POLICIES);',
|
|
51
|
+
'',
|
|
47
52
|
'export interface CreateAppOptions {',
|
|
48
53
|
' pool?: Pool;',
|
|
49
54
|
' authResolver?: AuthResolver;',
|
|
@@ -53,7 +58,7 @@ export class AppGenerator {
|
|
|
53
58
|
' const app = new Hono<AppEnv>();',
|
|
54
59
|
' app.use(logger());',
|
|
55
60
|
' app.use(prettyJSON());',
|
|
56
|
-
' app.use(createDbMiddleware({ pool: options.pool }));',
|
|
61
|
+
' app.use(createDbMiddleware({ pool: options.pool, createDbClient }));',
|
|
57
62
|
' app.use(createAuthMiddleware(options.authResolver ?? createJwtResolver()));',
|
|
58
63
|
' app.onError(handleError);',
|
|
59
64
|
'',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PACKAGE_NAME } from '../constants.js';
|
|
1
2
|
import { hasPolicies, normalizePolicies, serializePolicy, } from './utils/policy.js';
|
|
2
3
|
export class PolicyGenerator {
|
|
3
4
|
schema;
|
|
@@ -13,13 +14,7 @@ export class PolicyGenerator {
|
|
|
13
14
|
});
|
|
14
15
|
return [
|
|
15
16
|
'// Auto-generated by PolicyGenerator. Do not edit manually.',
|
|
16
|
-
|
|
17
|
-
'',
|
|
18
|
-
'export interface NormalizedPolicy {',
|
|
19
|
-
' role: string;',
|
|
20
|
-
" operations: PolicyOperation[] | 'all';",
|
|
21
|
-
' where?: string;',
|
|
22
|
-
'}',
|
|
17
|
+
`import type { NormalizedPolicy } from '${PACKAGE_NAME}/api/auth/policy';`,
|
|
23
18
|
'',
|
|
24
19
|
'export const POLICIES: Record<string, NormalizedPolicy[]> = {',
|
|
25
20
|
policyEntries.join(',\n'),
|
package/dist/cli/templates.js
CHANGED
|
@@ -59,10 +59,6 @@ export function createPackageJsonTemplate(projectName) {
|
|
|
59
59
|
version: '0.1.0',
|
|
60
60
|
private: true,
|
|
61
61
|
type: 'module',
|
|
62
|
-
imports: {
|
|
63
|
-
'generated/db.js': './generated/db.js',
|
|
64
|
-
'generated/policies.js': './generated/policies.js',
|
|
65
|
-
},
|
|
66
62
|
scripts: {
|
|
67
63
|
dev: `${PACKAGE_NAME} dev`,
|
|
68
64
|
generate: `${PACKAGE_NAME} generate`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "schematic-pg",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Single-file backend framework for PostgreSQL and Node.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"main": "./dist/index.js",
|
|
15
15
|
"types": "./dist/index.d.ts",
|
|
16
16
|
"bin": {
|
|
17
|
-
"schematic-pg": "
|
|
17
|
+
"schematic-pg": "dist/cli.js"
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"dist/",
|
|
@@ -25,10 +25,6 @@
|
|
|
25
25
|
"editors/vscode",
|
|
26
26
|
"editors/language-server"
|
|
27
27
|
],
|
|
28
|
-
"imports": {
|
|
29
|
-
"generated/db.js": "./generated/db.js",
|
|
30
|
-
"generated/policies.js": "./generated/policies.js"
|
|
31
|
-
},
|
|
32
28
|
"exports": {
|
|
33
29
|
".": {
|
|
34
30
|
"types": "./dist/index.d.ts",
|