@apso/cli 0.5.0 → 0.7.0
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/README.md +510 -1
- package/dist/commands/server/new.js +1 -1
- package/dist/commands/server/scaffold.js +19 -10
- package/dist/lib/apsorc-parser.d.ts +3 -0
- package/dist/lib/apsorc-parser.js +11 -6
- package/dist/lib/controller.js +3 -1
- package/dist/lib/dto.js +9 -9
- package/dist/lib/entity.js +6 -5
- package/dist/lib/guards.d.ts +4 -3
- package/dist/lib/guards.js +64 -25
- package/dist/lib/module.js +3 -1
- package/dist/lib/templates/guards/auth.guard.eta +228 -0
- package/dist/lib/templates/guards/guards.module.eta +73 -13
- package/dist/lib/templates/guards/index.eta +18 -0
- package/dist/lib/templates/guards/scope.guard.eta +12 -4
- package/dist/lib/types/auth.d.ts +203 -0
- package/dist/lib/types/auth.js +60 -0
- package/dist/lib/types/entity.d.ts +2 -2
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +8 -0
- package/dist/lib/types/relationship.d.ts +1 -1
- package/dist/lib/utils/casing.js +5 -5
- package/dist/lib/utils/field.js +2 -1
- package/dist/lib/utils/file-system.js +1 -1
- package/dist/lib/utils/relationships/parse-v1.js +2 -1
- package/dist/lib/utils/relationships/parse.js +117 -32
- package/dist/lib/utils/relationships/parse.spec.js +168 -141
- package/dist/test-nested-relationships.js +10 -10
- package/dist/tests/templates/entities/types/array-template.spec.js +45 -45
- package/dist/tests/templates/entities/types/bigint-template.spec.js +43 -43
- package/dist/tests/templates/entities/types/boolean-template.spec.js +44 -44
- package/dist/tests/templates/entities/types/bytea-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/char-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/date-template.spec.js +29 -29
- package/dist/tests/templates/entities/types/decimal-field-validation.spec.js +46 -46
- package/dist/tests/templates/entities/types/decimal-template.spec.js +46 -46
- package/dist/tests/templates/entities/types/double-template.spec.js +37 -34
- package/dist/tests/templates/entities/types/enum-template.spec.js +42 -42
- package/dist/tests/templates/entities/types/float-template.spec.js +37 -34
- package/dist/tests/templates/entities/types/geometry-template.spec.js +31 -31
- package/dist/tests/templates/entities/types/inet-template.spec.js +36 -36
- package/dist/tests/templates/entities/types/int4range-template.spec.js +45 -33
- package/dist/tests/templates/entities/types/integer-template.spec.js +40 -40
- package/dist/tests/templates/entities/types/interval-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/json-plain-template.spec.js +27 -27
- package/dist/tests/templates/entities/types/json-template.spec.js +19 -19
- package/dist/tests/templates/entities/types/jsonb-template.spec.js +19 -19
- package/dist/tests/templates/entities/types/money-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/numeric-template.spec.js +44 -44
- package/dist/tests/templates/entities/types/point-template.spec.js +37 -31
- package/dist/tests/templates/entities/types/polygon-template.spec.js +43 -31
- package/dist/tests/templates/entities/types/real-template.spec.js +34 -34
- package/dist/tests/templates/entities/types/serial-template.spec.js +62 -62
- package/dist/tests/templates/entities/types/smallint-template.spec.js +43 -43
- package/dist/tests/templates/entities/types/string-template.spec.js +59 -59
- package/dist/tests/templates/entities/types/text-template.spec.js +37 -37
- package/dist/tests/templates/entities/types/time-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/timestamp-template.spec.js +39 -39
- package/dist/tests/templates/entities/types/timetz-template.spec.js +35 -35
- package/dist/tests/templates/entities/types/tsvector-template.spec.js +28 -28
- package/dist/tests/templates/entities/types/uuid-template.spec.js +43 -43
- package/dist/tests/templates/entities/types/varchar-template.spec.js +59 -56
- package/dist/tests/templates/entities/types/xml-template.spec.js +28 -28
- package/dist/tests/templates/entities/utils/template-test-utils.d.ts +1 -1
- package/dist/tests/templates/entities/utils/template-test-utils.js +3 -3
- package/dist/tests/templates/entities/uuid-entity-template.spec.js +138 -138
- package/dist/tests/utils/relationship-deduplication.spec.js +11 -11
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -4,51 +4,111 @@ import { Module, Global } from '@nestjs/common';
|
|
|
4
4
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
5
5
|
import { APP_GUARD } from '@nestjs/core';
|
|
6
6
|
|
|
7
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
7
8
|
import { ScopeGuard } from './scope.guard';
|
|
9
|
+
<% } %>
|
|
10
|
+
<% if (it.authConfig) { %>
|
|
11
|
+
import { AuthGuard } from './auth.guard';
|
|
12
|
+
<% } %>
|
|
8
13
|
|
|
9
|
-
<% /* Import all entities
|
|
14
|
+
<% /* Import all entities for ScopeGuard (from sibling autogen folders) */ %>
|
|
15
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
16
|
+
// Entities for ScopeGuard
|
|
10
17
|
<% it.scopedEntities.forEach((entity) => { %>
|
|
11
|
-
import { <%= entity.name %> } from '
|
|
18
|
+
import { <%= entity.name %> } from '../<%= entity.name %>/<%= entity.name %>.entity';
|
|
12
19
|
<% }) %>
|
|
20
|
+
<% } %>
|
|
21
|
+
|
|
22
|
+
<% /* Import entities for AuthGuard (from sibling autogen folders) */ %>
|
|
23
|
+
<% if (it.authConfig) { %>
|
|
24
|
+
// Entities for AuthGuard
|
|
25
|
+
import { <%= it.authConfig.sessionEntity %> } from '../<%= it.authConfig.sessionEntity %>/<%= it.authConfig.sessionEntity %>.entity';
|
|
26
|
+
import { <%= it.authConfig.userEntity %> } from '../<%= it.authConfig.userEntity %>/<%= it.authConfig.userEntity %>.entity';
|
|
27
|
+
<% if (it.authConfig.accountUserEntity) { %>
|
|
28
|
+
import { <%= it.authConfig.accountUserEntity %> } from '../<%= it.authConfig.accountUserEntity %>/<%= it.authConfig.accountUserEntity %>.entity';
|
|
29
|
+
<% } %>
|
|
30
|
+
<% } %>
|
|
13
31
|
|
|
14
32
|
/**
|
|
15
|
-
* GuardsModule provides scope-based data isolation guards.
|
|
33
|
+
* GuardsModule provides authentication and scope-based data isolation guards.
|
|
16
34
|
*
|
|
17
|
-
* Auto-generated from .apsorc
|
|
35
|
+
* Auto-generated from .apsorc configuration.
|
|
36
|
+
* Generated at: <%= it.generatedAt %>
|
|
18
37
|
*
|
|
19
38
|
* Usage:
|
|
20
39
|
* 1. Import GuardsModule in your AppModule
|
|
21
40
|
* 2. Guards are NOT enabled globally by default (for backward compatibility)
|
|
22
|
-
* 3. To enable guards globally, uncomment the APP_GUARD
|
|
23
|
-
* 4. Or apply guards selectively using @UseGuards(ScopeGuard) on controllers
|
|
41
|
+
* 3. To enable guards globally, uncomment the APP_GUARD providers below
|
|
42
|
+
* 4. Or apply guards selectively using @UseGuards(AuthGuard, ScopeGuard) on controllers
|
|
43
|
+
*
|
|
44
|
+
<% if (it.authConfig) { %>
|
|
45
|
+
* AuthGuard:
|
|
46
|
+
* - Validates session tokens from cookies/headers
|
|
47
|
+
* - Loads user and organization context
|
|
48
|
+
* - Attaches normalized AuthContext to request.auth
|
|
49
|
+
* - Provider: <%= it.authConfig.provider %>
|
|
24
50
|
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*
|
|
51
|
+
<% } %>
|
|
52
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
53
|
+
* ScopeGuard:
|
|
54
|
+
* - Enforces data isolation based on scopeBy config
|
|
55
|
+
* - POST requests auto-inject scope fields from request.auth
|
|
28
56
|
* - GET requests auto-filter by scope fields
|
|
29
57
|
* - GET/PUT/PATCH/DELETE by ID verify resource ownership
|
|
30
58
|
*
|
|
59
|
+
<% } %>
|
|
31
60
|
* Decorators:
|
|
32
61
|
* - @Public() - Skip all guards for a route
|
|
62
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
33
63
|
* - @SkipScopeCheck() - Skip only scope checking
|
|
64
|
+
<% } %>
|
|
34
65
|
*/
|
|
35
66
|
@Global()
|
|
36
67
|
@Module({
|
|
37
68
|
imports: [
|
|
38
69
|
TypeOrmModule.forFeature([
|
|
39
|
-
<%
|
|
40
|
-
|
|
70
|
+
<% /* Collect all unique entities */ %>
|
|
71
|
+
<% const allEntities = new Set(); %>
|
|
72
|
+
<% if (it.scopedEntities) { it.scopedEntities.forEach(e => allEntities.add(e.name)); } %>
|
|
73
|
+
<% if (it.authConfig) { %>
|
|
74
|
+
<% allEntities.add(it.authConfig.sessionEntity); %>
|
|
75
|
+
<% allEntities.add(it.authConfig.userEntity); %>
|
|
76
|
+
<% if (it.authConfig.accountUserEntity) { allEntities.add(it.authConfig.accountUserEntity); } %>
|
|
77
|
+
<% } %>
|
|
78
|
+
<% const entityArray = Array.from(allEntities); %>
|
|
79
|
+
<% entityArray.forEach((entity, index) => { %>
|
|
80
|
+
<%= entity %><%= index < entityArray.length - 1 ? ',' : '' %>
|
|
41
81
|
<% }) %>
|
|
42
82
|
]),
|
|
43
83
|
],
|
|
44
84
|
providers: [
|
|
85
|
+
<% if (it.authConfig) { %>
|
|
86
|
+
AuthGuard,
|
|
87
|
+
<% } %>
|
|
88
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
45
89
|
ScopeGuard,
|
|
46
|
-
|
|
90
|
+
<% } %>
|
|
91
|
+
// UNCOMMENT BELOW TO ENABLE GLOBAL GUARDS
|
|
92
|
+
<% if (it.authConfig) { %>
|
|
93
|
+
// {
|
|
94
|
+
// provide: APP_GUARD,
|
|
95
|
+
// useClass: AuthGuard,
|
|
96
|
+
// },
|
|
97
|
+
<% } %>
|
|
98
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
47
99
|
// {
|
|
48
100
|
// provide: APP_GUARD,
|
|
49
101
|
// useClass: ScopeGuard,
|
|
50
102
|
// },
|
|
103
|
+
<% } %>
|
|
104
|
+
],
|
|
105
|
+
exports: [
|
|
106
|
+
<% if (it.authConfig) { %>
|
|
107
|
+
AuthGuard,
|
|
108
|
+
<% } %>
|
|
109
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
110
|
+
ScopeGuard,
|
|
111
|
+
<% } %>
|
|
51
112
|
],
|
|
52
|
-
exports: [ScopeGuard],
|
|
53
113
|
})
|
|
54
114
|
export class GuardsModule {}
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
<%~ includeFile('../header.eta') %>
|
|
2
2
|
|
|
3
|
+
<% if (it.authConfig) { %>
|
|
4
|
+
export * from './auth.guard';
|
|
5
|
+
<% } %>
|
|
6
|
+
<% if (it.scopedEntities && it.scopedEntities.length > 0) { %>
|
|
7
|
+
<% if (it.authConfig) { %>
|
|
8
|
+
// When auth is configured, only export scope-specific items from scope.guard
|
|
9
|
+
// to avoid duplicate exports (Public, IS_PUBLIC_KEY come from auth.guard)
|
|
10
|
+
export {
|
|
11
|
+
ScopeGuard,
|
|
12
|
+
SKIP_SCOPE_CHECK,
|
|
13
|
+
SkipScopeCheck,
|
|
14
|
+
ScopeConfig,
|
|
15
|
+
ScopeField,
|
|
16
|
+
ENTITY_SCOPES,
|
|
17
|
+
} from './scope.guard';
|
|
18
|
+
<% } else { %>
|
|
3
19
|
export * from './scope.guard';
|
|
20
|
+
<% } %>
|
|
21
|
+
<% } %>
|
|
4
22
|
export * from './guards.module';
|
|
@@ -10,9 +10,9 @@ import { Reflector } from '@nestjs/core';
|
|
|
10
10
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
11
11
|
import { Repository } from 'typeorm';
|
|
12
12
|
|
|
13
|
-
<% /* Import all entities that have scoped relationships */ %>
|
|
13
|
+
<% /* Import all entities that have scoped relationships (from sibling autogen folders) */ %>
|
|
14
14
|
<% it.scopedEntities.forEach((entity) => { %>
|
|
15
|
-
import { <%= entity.name %> } from '
|
|
15
|
+
import { <%= entity.name %> } from '../<%= entity.name %>/<%= entity.name %>.entity';
|
|
16
16
|
<% }) %>
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -28,6 +28,13 @@ export const SkipScopeCheck = () =>
|
|
|
28
28
|
);
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
+
<% if (it.authConfig) { %>
|
|
32
|
+
/**
|
|
33
|
+
* Import Public decorator from auth.guard to avoid duplicate exports
|
|
34
|
+
*/
|
|
35
|
+
import { IS_PUBLIC_KEY, Public } from './auth.guard';
|
|
36
|
+
export { IS_PUBLIC_KEY, Public };
|
|
37
|
+
<% } else { %>
|
|
31
38
|
/**
|
|
32
39
|
* Decorator to mark routes as public (no auth required)
|
|
33
40
|
*/
|
|
@@ -40,6 +47,7 @@ export const Public = () =>
|
|
|
40
47
|
descriptor?.value || target,
|
|
41
48
|
);
|
|
42
49
|
};
|
|
50
|
+
<% } %>
|
|
43
51
|
|
|
44
52
|
/**
|
|
45
53
|
* Scope configuration for each entity
|
|
@@ -87,8 +95,8 @@ export const ENTITY_SCOPES: Record<string, ScopeConfig> = {
|
|
|
87
95
|
<% }) %>
|
|
88
96
|
],
|
|
89
97
|
injectOnCreate: <%= entity.injectOnCreate %>,
|
|
90
|
-
enforceOn: [
|
|
91
|
-
bypassRoles: [
|
|
98
|
+
enforceOn: [<%~ entity.enforceOn.map(op => `'${op}'`).join(', ') %>],
|
|
99
|
+
bypassRoles: [<%~ entity.bypassRoles.map(role => `'${role}'`).join(', ') %>],
|
|
92
100
|
}<%= index < it.scopedEntities.length - 1 ? ',' : '' %>
|
|
93
101
|
<% }) %>
|
|
94
102
|
};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supported authentication provider types
|
|
3
|
+
*/
|
|
4
|
+
export type AuthProviderType = "better-auth" | "custom-db-session" | "auth0" | "clerk" | "cognito" | "api-key";
|
|
5
|
+
/**
|
|
6
|
+
* Base configuration common to all auth providers
|
|
7
|
+
*/
|
|
8
|
+
export interface BaseAuthConfig {
|
|
9
|
+
/**
|
|
10
|
+
* The authentication provider type
|
|
11
|
+
*/
|
|
12
|
+
provider: AuthProviderType;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Configuration for DB-backed session providers (Better Auth, custom-db-session)
|
|
16
|
+
*/
|
|
17
|
+
export interface DbSessionAuthConfig extends BaseAuthConfig {
|
|
18
|
+
provider: "better-auth" | "custom-db-session";
|
|
19
|
+
/**
|
|
20
|
+
* Entity name for sessions. Default: "session"
|
|
21
|
+
*/
|
|
22
|
+
sessionEntity?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Entity name for users. Default: "User"
|
|
25
|
+
*/
|
|
26
|
+
userEntity?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Junction entity for user-organization mapping. Default: "AccountUser"
|
|
29
|
+
*/
|
|
30
|
+
accountUserEntity?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Cookie name prefix for session tokens. Default: service name
|
|
33
|
+
*/
|
|
34
|
+
cookiePrefix?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Field name on accountUserEntity for organization ID. Default: "organizationId"
|
|
37
|
+
*/
|
|
38
|
+
organizationField?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Field name on accountUserEntity for user's role. Default: "role"
|
|
41
|
+
*/
|
|
42
|
+
roleField?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* JWT configuration for token-based providers
|
|
46
|
+
*/
|
|
47
|
+
export interface JwtConfig {
|
|
48
|
+
/**
|
|
49
|
+
* The JWT issuer URL (e.g., "https://your-tenant.auth0.com/")
|
|
50
|
+
*/
|
|
51
|
+
issuer: string;
|
|
52
|
+
/**
|
|
53
|
+
* Expected audience for the JWT
|
|
54
|
+
*/
|
|
55
|
+
audience: string;
|
|
56
|
+
/**
|
|
57
|
+
* JWKS URI for key rotation. If not provided, uses issuer + /.well-known/jwks.json
|
|
58
|
+
*/
|
|
59
|
+
jwksUri?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Algorithms to accept. Default: ["RS256"]
|
|
62
|
+
*/
|
|
63
|
+
algorithms?: string[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Claim mapping for JWT providers
|
|
67
|
+
*/
|
|
68
|
+
export interface JwtClaimsMapping {
|
|
69
|
+
/**
|
|
70
|
+
* Claim for user ID. Default: "sub"
|
|
71
|
+
*/
|
|
72
|
+
userId?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Claim for workspace/organization ID
|
|
75
|
+
*/
|
|
76
|
+
workspaceId?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Claim for organization ID (alias for workspaceId)
|
|
79
|
+
*/
|
|
80
|
+
organizationId?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Claim for user roles array
|
|
83
|
+
*/
|
|
84
|
+
roles?: string;
|
|
85
|
+
/**
|
|
86
|
+
* Claim for user email
|
|
87
|
+
*/
|
|
88
|
+
email?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Configuration for JWT-based providers (Auth0, Cognito, Clerk)
|
|
92
|
+
*/
|
|
93
|
+
export interface JwtAuthConfig extends BaseAuthConfig {
|
|
94
|
+
provider: "auth0" | "clerk" | "cognito";
|
|
95
|
+
/**
|
|
96
|
+
* JWT verification configuration
|
|
97
|
+
*/
|
|
98
|
+
jwt: JwtConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Mapping of JWT claims to AuthContext fields
|
|
101
|
+
*/
|
|
102
|
+
claims?: JwtClaimsMapping;
|
|
103
|
+
/**
|
|
104
|
+
* Optional: If you want to sync/verify users against a local User entity
|
|
105
|
+
*/
|
|
106
|
+
userEntity?: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Configuration for API key authentication
|
|
110
|
+
*/
|
|
111
|
+
export interface ApiKeyAuthConfig extends BaseAuthConfig {
|
|
112
|
+
provider: "api-key";
|
|
113
|
+
/**
|
|
114
|
+
* Header name for API key. Default: "x-api-key"
|
|
115
|
+
*/
|
|
116
|
+
apiKeyHeader?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Entity name for API keys. Default: "ApiKey"
|
|
119
|
+
*/
|
|
120
|
+
apiKeyEntity?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Field name on apiKeyEntity for workspace/organization ID
|
|
123
|
+
*/
|
|
124
|
+
workspaceField?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Field name on apiKeyEntity for role/permissions
|
|
127
|
+
*/
|
|
128
|
+
roleField?: string;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Union type of all auth configurations
|
|
132
|
+
*/
|
|
133
|
+
export type AuthConfig = DbSessionAuthConfig | JwtAuthConfig | ApiKeyAuthConfig;
|
|
134
|
+
/**
|
|
135
|
+
* The normalized AuthContext that all providers produce.
|
|
136
|
+
* This is what scopeBy and RBAC consume.
|
|
137
|
+
*/
|
|
138
|
+
export interface AuthContext {
|
|
139
|
+
/**
|
|
140
|
+
* The authenticated user's ID
|
|
141
|
+
*/
|
|
142
|
+
userId?: string;
|
|
143
|
+
/**
|
|
144
|
+
* The user's email (if available)
|
|
145
|
+
*/
|
|
146
|
+
email?: string;
|
|
147
|
+
/**
|
|
148
|
+
* The workspace/tenant ID (generic term)
|
|
149
|
+
*/
|
|
150
|
+
workspaceId?: string;
|
|
151
|
+
/**
|
|
152
|
+
* The organization ID (alias for workspaceId in multi-tenant contexts)
|
|
153
|
+
*/
|
|
154
|
+
organizationId?: string;
|
|
155
|
+
/**
|
|
156
|
+
* Array of roles/permissions the user has
|
|
157
|
+
*/
|
|
158
|
+
roles: string[];
|
|
159
|
+
/**
|
|
160
|
+
* For API key auth: the service/key identifier
|
|
161
|
+
*/
|
|
162
|
+
serviceId?: string;
|
|
163
|
+
/**
|
|
164
|
+
* Raw user object (provider-specific, for advanced use cases)
|
|
165
|
+
*/
|
|
166
|
+
user?: unknown;
|
|
167
|
+
/**
|
|
168
|
+
* Raw session object (provider-specific, for advanced use cases)
|
|
169
|
+
*/
|
|
170
|
+
session?: unknown;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Default values for DB session auth configuration
|
|
174
|
+
*/
|
|
175
|
+
export declare const DB_SESSION_AUTH_DEFAULTS: Required<Omit<DbSessionAuthConfig, "provider" | "cookiePrefix">> & {
|
|
176
|
+
cookiePrefix?: string;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Default values for JWT auth configuration
|
|
180
|
+
*/
|
|
181
|
+
export declare const JWT_AUTH_DEFAULTS: Required<Pick<JwtAuthConfig, "claims">> & Partial<JwtConfig>;
|
|
182
|
+
/**
|
|
183
|
+
* Default values for API key auth configuration
|
|
184
|
+
*/
|
|
185
|
+
export declare const API_KEY_AUTH_DEFAULTS: Required<Omit<ApiKeyAuthConfig, "provider" | "workspaceField" | "roleField">>;
|
|
186
|
+
/**
|
|
187
|
+
* Type guard: Check if auth config is DB session based
|
|
188
|
+
* @param {AuthConfig} auth - The auth configuration to check
|
|
189
|
+
* @returns {boolean} True if the auth config is DB session based
|
|
190
|
+
*/
|
|
191
|
+
export declare function isDbSessionAuth(auth: AuthConfig): auth is DbSessionAuthConfig;
|
|
192
|
+
/**
|
|
193
|
+
* Type guard: Check if auth config is JWT based
|
|
194
|
+
* @param {AuthConfig} auth - The auth configuration to check
|
|
195
|
+
* @returns {boolean} True if the auth config is JWT based
|
|
196
|
+
*/
|
|
197
|
+
export declare function isJwtAuth(auth: AuthConfig): auth is JwtAuthConfig;
|
|
198
|
+
/**
|
|
199
|
+
* Type guard: Check if auth config is API key based
|
|
200
|
+
* @param {AuthConfig} auth - The auth configuration to check
|
|
201
|
+
* @returns {boolean} True if the auth config is API key based
|
|
202
|
+
*/
|
|
203
|
+
export declare function isApiKeyAuth(auth: AuthConfig): auth is ApiKeyAuthConfig;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isApiKeyAuth = exports.isJwtAuth = exports.isDbSessionAuth = exports.API_KEY_AUTH_DEFAULTS = exports.JWT_AUTH_DEFAULTS = exports.DB_SESSION_AUTH_DEFAULTS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Default values for DB session auth configuration
|
|
6
|
+
*/
|
|
7
|
+
exports.DB_SESSION_AUTH_DEFAULTS = {
|
|
8
|
+
sessionEntity: "session",
|
|
9
|
+
userEntity: "User",
|
|
10
|
+
accountUserEntity: "AccountUser",
|
|
11
|
+
organizationField: "organizationId",
|
|
12
|
+
roleField: "role",
|
|
13
|
+
cookiePrefix: undefined, // Will use service name if not specified
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Default values for JWT auth configuration
|
|
17
|
+
*/
|
|
18
|
+
exports.JWT_AUTH_DEFAULTS = {
|
|
19
|
+
claims: {
|
|
20
|
+
userId: "sub",
|
|
21
|
+
email: "email",
|
|
22
|
+
roles: "roles",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Default values for API key auth configuration
|
|
27
|
+
*/
|
|
28
|
+
exports.API_KEY_AUTH_DEFAULTS = {
|
|
29
|
+
apiKeyHeader: "x-api-key",
|
|
30
|
+
apiKeyEntity: "ApiKey",
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Type guard: Check if auth config is DB session based
|
|
34
|
+
* @param {AuthConfig} auth - The auth configuration to check
|
|
35
|
+
* @returns {boolean} True if the auth config is DB session based
|
|
36
|
+
*/
|
|
37
|
+
function isDbSessionAuth(auth) {
|
|
38
|
+
return auth.provider === "better-auth" || auth.provider === "custom-db-session";
|
|
39
|
+
}
|
|
40
|
+
exports.isDbSessionAuth = isDbSessionAuth;
|
|
41
|
+
/**
|
|
42
|
+
* Type guard: Check if auth config is JWT based
|
|
43
|
+
* @param {AuthConfig} auth - The auth configuration to check
|
|
44
|
+
* @returns {boolean} True if the auth config is JWT based
|
|
45
|
+
*/
|
|
46
|
+
function isJwtAuth(auth) {
|
|
47
|
+
return (auth.provider === "auth0" ||
|
|
48
|
+
auth.provider === "clerk" ||
|
|
49
|
+
auth.provider === "cognito");
|
|
50
|
+
}
|
|
51
|
+
exports.isJwtAuth = isJwtAuth;
|
|
52
|
+
/**
|
|
53
|
+
* Type guard: Check if auth config is API key based
|
|
54
|
+
* @param {AuthConfig} auth - The auth configuration to check
|
|
55
|
+
* @returns {boolean} True if the auth config is API key based
|
|
56
|
+
*/
|
|
57
|
+
function isApiKeyAuth(auth) {
|
|
58
|
+
return auth.provider === "api-key";
|
|
59
|
+
}
|
|
60
|
+
exports.isApiKeyAuth = isApiKeyAuth;
|
|
@@ -5,7 +5,7 @@ import { Association } from "./relationship";
|
|
|
5
5
|
/**
|
|
6
6
|
* Operations that can have scope enforcement applied
|
|
7
7
|
*/
|
|
8
|
-
export type ScopeOperation =
|
|
8
|
+
export type ScopeOperation = "find" | "get" | "create" | "update" | "delete";
|
|
9
9
|
/**
|
|
10
10
|
* Configuration options for scope enforcement behavior
|
|
11
11
|
*/
|
|
@@ -28,7 +28,7 @@ export interface Entity {
|
|
|
28
28
|
name: string;
|
|
29
29
|
created_at?: boolean;
|
|
30
30
|
updated_at?: boolean;
|
|
31
|
-
primaryKeyType?:
|
|
31
|
+
primaryKeyType?: "serial" | "uuid";
|
|
32
32
|
fields?: Field[];
|
|
33
33
|
indexes?: Index[];
|
|
34
34
|
uniques?: Unique[];
|
|
@@ -3,3 +3,4 @@ export { FieldType, Field, ComputedField } from "./field";
|
|
|
3
3
|
export { Index } from "./indices";
|
|
4
4
|
export { JSONValue } from "./json";
|
|
5
5
|
export { RelationshipType, Association, ApsorcRelationship, Relationship, RelationshipForTemplate, RelationshipMap, } from "./relationship";
|
|
6
|
+
export { AuthProviderType, BaseAuthConfig, DbSessionAuthConfig, JwtConfig, JwtClaimsMapping, JwtAuthConfig, ApiKeyAuthConfig, AuthConfig, AuthContext, DB_SESSION_AUTH_DEFAULTS, JWT_AUTH_DEFAULTS, API_KEY_AUTH_DEFAULTS, isDbSessionAuth, isJwtAuth, isApiKeyAuth, } from "./auth";
|
package/dist/lib/types/index.js
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isApiKeyAuth = exports.isJwtAuth = exports.isDbSessionAuth = exports.API_KEY_AUTH_DEFAULTS = exports.JWT_AUTH_DEFAULTS = exports.DB_SESSION_AUTH_DEFAULTS = void 0;
|
|
4
|
+
var auth_1 = require("./auth");
|
|
5
|
+
Object.defineProperty(exports, "DB_SESSION_AUTH_DEFAULTS", { enumerable: true, get: function () { return auth_1.DB_SESSION_AUTH_DEFAULTS; } });
|
|
6
|
+
Object.defineProperty(exports, "JWT_AUTH_DEFAULTS", { enumerable: true, get: function () { return auth_1.JWT_AUTH_DEFAULTS; } });
|
|
7
|
+
Object.defineProperty(exports, "API_KEY_AUTH_DEFAULTS", { enumerable: true, get: function () { return auth_1.API_KEY_AUTH_DEFAULTS; } });
|
|
8
|
+
Object.defineProperty(exports, "isDbSessionAuth", { enumerable: true, get: function () { return auth_1.isDbSessionAuth; } });
|
|
9
|
+
Object.defineProperty(exports, "isJwtAuth", { enumerable: true, get: function () { return auth_1.isJwtAuth; } });
|
|
10
|
+
Object.defineProperty(exports, "isApiKeyAuth", { enumerable: true, get: function () { return auth_1.isApiKeyAuth; } });
|
|
@@ -36,7 +36,7 @@ export interface RelationshipForTemplate extends Relationship {
|
|
|
36
36
|
joinTable: boolean;
|
|
37
37
|
biDirectional: boolean;
|
|
38
38
|
inversePropertyName?: string;
|
|
39
|
-
referencedEntityPrimaryKeyType?:
|
|
39
|
+
referencedEntityPrimaryKeyType?: "serial" | "uuid";
|
|
40
40
|
}
|
|
41
41
|
export type RelationshipMap = {
|
|
42
42
|
[key: string]: Relationship[];
|
package/dist/lib/utils/casing.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.pascalCase = exports.snakeCase = exports.camelCase = void 0;
|
|
4
4
|
function camelCase(str) {
|
|
5
|
-
return str
|
|
5
|
+
return (str
|
|
6
6
|
// Insert a space before all caps that are followed by lower case (for PascalCase)
|
|
7
|
-
.replace(/([\da-z])([A-Z])/g,
|
|
7
|
+
.replace(/([\da-z])([A-Z])/g, "$1 $2")
|
|
8
8
|
// Replace all separators with spaces
|
|
9
|
-
.replace(/[ _-]+/g,
|
|
9
|
+
.replace(/[ _-]+/g, " ")
|
|
10
10
|
// Lowercase the string, then uppercase the first letter of each word (except the first)
|
|
11
11
|
.toLowerCase()
|
|
12
|
-
.replace(/ (\w)/g, (_, c) => c ? c.toUpperCase() :
|
|
12
|
+
.replace(/ (\w)/g, (_, c) => (c ? c.toUpperCase() : ""))
|
|
13
13
|
// Remove spaces
|
|
14
|
-
.replace(/ /g,
|
|
14
|
+
.replace(/ /g, ""));
|
|
15
15
|
}
|
|
16
16
|
exports.camelCase = camelCase;
|
|
17
17
|
const snakeCase = (str) => str[0].toLowerCase() +
|
package/dist/lib/utils/field.js
CHANGED
|
@@ -102,7 +102,8 @@ const validateDecimalField = (field) => {
|
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
104
|
// Validate precision
|
|
105
|
-
if (field.precision !== undefined &&
|
|
105
|
+
if (field.precision !== undefined &&
|
|
106
|
+
(field.precision < 1 || field.precision > 131072)) {
|
|
106
107
|
throw new Error(`${field.name}: Invalid precision value ${field.precision}. Must be between 1 and 131072.`);
|
|
107
108
|
}
|
|
108
109
|
// Validate scale
|
|
@@ -54,7 +54,7 @@ function withGeneratedMeta(data) {
|
|
|
54
54
|
return {
|
|
55
55
|
...data,
|
|
56
56
|
generatedAt: new Date().toISOString(),
|
|
57
|
-
generatedBy: process.env.USER || process.env.USERNAME ||
|
|
57
|
+
generatedBy: process.env.USER || process.env.USERNAME || "unknown",
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
exports.withGeneratedMeta = withGeneratedMeta;
|
|
@@ -79,7 +79,8 @@ const parseV1Relationships = (entities) => {
|
|
|
79
79
|
for (const apsorcRelationship of apsorcRelationships) {
|
|
80
80
|
const parsedResult = (0, parse_1.parseRelationship)(apsorcRelationship, apsorcRelationships);
|
|
81
81
|
for (const key of Object.keys(parsedResult)) {
|
|
82
|
-
if (parsedResult[key] && parsedResult[key].length > 0) {
|
|
82
|
+
if (parsedResult[key] && parsedResult[key].length > 0) {
|
|
83
|
+
// Ensure non-empty result
|
|
83
84
|
relationshipMap[key] = [
|
|
84
85
|
...(relationshipMap[key] || []),
|
|
85
86
|
...parsedResult[key],
|