@objectstack/plugin-auth 2.0.2
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/.turbo/turbo-build.log +22 -0
- package/CHANGELOG.md +32 -0
- package/IMPLEMENTATION_SUMMARY.md +150 -0
- package/LICENSE +202 -0
- package/README.md +120 -0
- package/dist/index.d.mts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +165 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +138 -0
- package/dist/index.mjs.map +1 -0
- package/examples/basic-usage.ts +95 -0
- package/package.json +29 -0
- package/src/auth-plugin.test.ts +216 -0
- package/src/auth-plugin.ts +222 -0
- package/src/index.ts +11 -0
- package/tsconfig.json +9 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AuthPlugin: () => AuthPlugin
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/auth-plugin.ts
|
|
28
|
+
var AuthPlugin = class {
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.name = "com.objectstack.auth";
|
|
31
|
+
this.type = "standard";
|
|
32
|
+
this.version = "1.0.0";
|
|
33
|
+
this.dependencies = ["com.objectstack.server.hono"];
|
|
34
|
+
this.authManager = null;
|
|
35
|
+
this.options = {
|
|
36
|
+
registerRoutes: true,
|
|
37
|
+
basePath: "/api/v1/auth",
|
|
38
|
+
...options
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
async init(ctx) {
|
|
42
|
+
ctx.logger.info("Initializing Auth Plugin...");
|
|
43
|
+
if (!this.options.secret) {
|
|
44
|
+
throw new Error("AuthPlugin: secret is required");
|
|
45
|
+
}
|
|
46
|
+
this.authManager = new AuthManager(this.options);
|
|
47
|
+
ctx.registerService("auth", this.authManager);
|
|
48
|
+
ctx.logger.info("Auth Plugin initialized successfully");
|
|
49
|
+
}
|
|
50
|
+
async start(ctx) {
|
|
51
|
+
ctx.logger.info("Starting Auth Plugin...");
|
|
52
|
+
if (!this.authManager) {
|
|
53
|
+
throw new Error("Auth manager not initialized");
|
|
54
|
+
}
|
|
55
|
+
if (this.options.registerRoutes) {
|
|
56
|
+
try {
|
|
57
|
+
const httpServer = ctx.getService("http-server");
|
|
58
|
+
this.registerAuthRoutes(httpServer, ctx);
|
|
59
|
+
ctx.logger.info(`Auth routes registered at ${this.options.basePath}`);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
62
|
+
ctx.logger.error("Failed to register auth routes:", err);
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
ctx.logger.info("Auth Plugin started successfully");
|
|
67
|
+
}
|
|
68
|
+
async destroy() {
|
|
69
|
+
this.authManager = null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Register authentication routes with HTTP server
|
|
73
|
+
*/
|
|
74
|
+
registerAuthRoutes(httpServer, ctx) {
|
|
75
|
+
if (!this.authManager) return;
|
|
76
|
+
const basePath = this.options.basePath || "/api/v1/auth";
|
|
77
|
+
httpServer.post(`${basePath}/login`, async (req, res) => {
|
|
78
|
+
try {
|
|
79
|
+
const body = req.body;
|
|
80
|
+
const result = await this.authManager.login(body);
|
|
81
|
+
res.status(200).json(result);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
84
|
+
ctx.logger.error("Login error:", err);
|
|
85
|
+
res.status(401).json({
|
|
86
|
+
success: false,
|
|
87
|
+
error: err.message
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
httpServer.post(`${basePath}/register`, async (req, res) => {
|
|
92
|
+
try {
|
|
93
|
+
const body = req.body;
|
|
94
|
+
const result = await this.authManager.register(body);
|
|
95
|
+
res.status(201).json(result);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
98
|
+
ctx.logger.error("Registration error:", err);
|
|
99
|
+
res.status(400).json({
|
|
100
|
+
success: false,
|
|
101
|
+
error: err.message
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
httpServer.post(`${basePath}/logout`, async (req, res) => {
|
|
106
|
+
try {
|
|
107
|
+
const authHeader = req.headers["authorization"];
|
|
108
|
+
const token = typeof authHeader === "string" ? authHeader.replace("Bearer ", "") : void 0;
|
|
109
|
+
await this.authManager.logout(token);
|
|
110
|
+
res.status(200).json({ success: true });
|
|
111
|
+
} catch (error) {
|
|
112
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
113
|
+
ctx.logger.error("Logout error:", err);
|
|
114
|
+
res.status(400).json({
|
|
115
|
+
success: false,
|
|
116
|
+
error: err.message
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
httpServer.get(`${basePath}/session`, async (req, res) => {
|
|
121
|
+
try {
|
|
122
|
+
const authHeader = req.headers["authorization"];
|
|
123
|
+
const token = typeof authHeader === "string" ? authHeader.replace("Bearer ", "") : void 0;
|
|
124
|
+
const session = await this.authManager.getSession(token);
|
|
125
|
+
res.status(200).json({ success: true, data: session });
|
|
126
|
+
} catch (error) {
|
|
127
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
128
|
+
res.status(401).json({
|
|
129
|
+
success: false,
|
|
130
|
+
error: err.message
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
ctx.logger.debug("Auth routes registered:", {
|
|
135
|
+
basePath,
|
|
136
|
+
routes: [
|
|
137
|
+
`POST ${basePath}/login`,
|
|
138
|
+
`POST ${basePath}/register`,
|
|
139
|
+
`POST ${basePath}/logout`,
|
|
140
|
+
`GET ${basePath}/session`
|
|
141
|
+
]
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
var AuthManager = class {
|
|
146
|
+
constructor(_config) {
|
|
147
|
+
}
|
|
148
|
+
async login(_credentials) {
|
|
149
|
+
throw new Error("Login not yet implemented");
|
|
150
|
+
}
|
|
151
|
+
async register(_userData) {
|
|
152
|
+
throw new Error("Registration not yet implemented");
|
|
153
|
+
}
|
|
154
|
+
async logout(_token) {
|
|
155
|
+
throw new Error("Logout not yet implemented");
|
|
156
|
+
}
|
|
157
|
+
async getSession(_token) {
|
|
158
|
+
throw new Error("Session retrieval not yet implemented");
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
162
|
+
0 && (module.exports = {
|
|
163
|
+
AuthPlugin
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/auth-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * @objectstack/plugin-auth\n * \n * Authentication & Identity Plugin for ObjectStack\n * Powered by better-auth for robust, secure authentication\n */\n\nexport * from './auth-plugin';\nexport type { AuthConfig, AuthProviderConfig, AuthPluginConfig } from '@objectstack/spec/system';\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext, IHttpServer } from '@objectstack/core';\nimport { AuthConfig } from '@objectstack/spec/system';\n\n/**\n * Auth Plugin Options\n * Extends AuthConfig from spec with additional runtime options\n */\nexport interface AuthPluginOptions extends Partial<AuthConfig> {\n /**\n * Whether to automatically register auth routes\n * @default true\n */\n registerRoutes?: boolean;\n \n /**\n * Base path for auth routes\n * @default '/api/v1/auth'\n */\n basePath?: string;\n}\n\n/**\n * Authentication Plugin\n * \n * Provides authentication and identity services for ObjectStack applications.\n * \n * Features:\n * - Session management\n * - User registration/login\n * - OAuth providers (Google, GitHub, etc.)\n * - Organization/team support\n * - 2FA, passkeys, magic links\n * \n * This plugin registers:\n * - `auth` service (auth manager instance)\n * - HTTP routes for authentication endpoints\n * \n * @planned This is a stub implementation. Full better-auth integration\n * will be added in a future version. For now, it provides the plugin\n * structure and basic route registration.\n */\nexport class AuthPlugin implements Plugin {\n name = 'com.objectstack.auth';\n type = 'standard';\n version = '1.0.0';\n dependencies = ['com.objectstack.server.hono']; // Requires HTTP server\n \n private options: AuthPluginOptions;\n private authManager: AuthManager | null = null;\n\n constructor(options: AuthPluginOptions = {}) {\n this.options = {\n registerRoutes: true,\n basePath: '/api/v1/auth',\n ...options\n };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Initializing Auth Plugin...');\n\n // Validate required configuration\n if (!this.options.secret) {\n throw new Error('AuthPlugin: secret is required');\n }\n\n // Initialize auth manager\n this.authManager = new AuthManager(this.options);\n\n // Register auth service\n ctx.registerService('auth', this.authManager);\n \n ctx.logger.info('Auth Plugin initialized successfully');\n }\n\n async start(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Starting Auth Plugin...');\n\n if (!this.authManager) {\n throw new Error('Auth manager not initialized');\n }\n\n // Register HTTP routes if enabled\n if (this.options.registerRoutes) {\n try {\n const httpServer = ctx.getService<IHttpServer>('http-server');\n this.registerAuthRoutes(httpServer, ctx);\n ctx.logger.info(`Auth routes registered at ${this.options.basePath}`);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Failed to register auth routes:', err);\n throw err;\n }\n }\n\n ctx.logger.info('Auth Plugin started successfully');\n }\n\n async destroy(): Promise<void> {\n // Cleanup if needed\n this.authManager = null;\n }\n\n /**\n * Register authentication routes with HTTP server\n */\n private registerAuthRoutes(httpServer: IHttpServer, ctx: PluginContext): void {\n if (!this.authManager) return;\n\n const basePath = this.options.basePath || '/api/v1/auth';\n\n // Login endpoint\n httpServer.post(`${basePath}/login`, async (req, res) => {\n try {\n const body = req.body;\n const result = await this.authManager!.login(body);\n res.status(200).json(result);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Login error:', err);\n res.status(401).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n // Register endpoint\n httpServer.post(`${basePath}/register`, async (req, res) => {\n try {\n const body = req.body;\n const result = await this.authManager!.register(body);\n res.status(201).json(result);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Registration error:', err);\n res.status(400).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n // Logout endpoint\n httpServer.post(`${basePath}/logout`, async (req, res) => {\n try {\n const authHeader = req.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : undefined;\n await this.authManager!.logout(token);\n res.status(200).json({ success: true });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Logout error:', err);\n res.status(400).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n // Session endpoint\n httpServer.get(`${basePath}/session`, async (req, res) => {\n try {\n const authHeader = req.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : undefined;\n const session = await this.authManager!.getSession(token);\n res.status(200).json({ success: true, data: session });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n res.status(401).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n ctx.logger.debug('Auth routes registered:', {\n basePath,\n routes: [\n `POST ${basePath}/login`,\n `POST ${basePath}/register`,\n `POST ${basePath}/logout`,\n `GET ${basePath}/session`,\n ],\n });\n }\n}\n\n/**\n * Auth Manager\n * \n * @planned This is a stub implementation. Real authentication logic\n * will be implemented using better-auth or similar library in future versions.\n */\nclass AuthManager {\n constructor(_config: AuthPluginOptions) {\n // Store config for future use\n }\n\n async login(_credentials: any): Promise<any> {\n // @planned Implement actual login logic with better-auth\n throw new Error('Login not yet implemented');\n }\n\n async register(_userData: any): Promise<any> {\n // @planned Implement actual registration logic with better-auth\n throw new Error('Registration not yet implemented');\n }\n\n async logout(_token?: string): Promise<void> {\n // @planned Implement actual logout logic\n throw new Error('Logout not yet implemented');\n }\n\n async getSession(_token?: string): Promise<any> {\n // @planned Implement actual session retrieval\n throw new Error('Session retrieval not yet implemented');\n }\n}\n\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// src/auth-plugin.ts
|
|
2
|
+
var AuthPlugin = class {
|
|
3
|
+
constructor(options = {}) {
|
|
4
|
+
this.name = "com.objectstack.auth";
|
|
5
|
+
this.type = "standard";
|
|
6
|
+
this.version = "1.0.0";
|
|
7
|
+
this.dependencies = ["com.objectstack.server.hono"];
|
|
8
|
+
this.authManager = null;
|
|
9
|
+
this.options = {
|
|
10
|
+
registerRoutes: true,
|
|
11
|
+
basePath: "/api/v1/auth",
|
|
12
|
+
...options
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async init(ctx) {
|
|
16
|
+
ctx.logger.info("Initializing Auth Plugin...");
|
|
17
|
+
if (!this.options.secret) {
|
|
18
|
+
throw new Error("AuthPlugin: secret is required");
|
|
19
|
+
}
|
|
20
|
+
this.authManager = new AuthManager(this.options);
|
|
21
|
+
ctx.registerService("auth", this.authManager);
|
|
22
|
+
ctx.logger.info("Auth Plugin initialized successfully");
|
|
23
|
+
}
|
|
24
|
+
async start(ctx) {
|
|
25
|
+
ctx.logger.info("Starting Auth Plugin...");
|
|
26
|
+
if (!this.authManager) {
|
|
27
|
+
throw new Error("Auth manager not initialized");
|
|
28
|
+
}
|
|
29
|
+
if (this.options.registerRoutes) {
|
|
30
|
+
try {
|
|
31
|
+
const httpServer = ctx.getService("http-server");
|
|
32
|
+
this.registerAuthRoutes(httpServer, ctx);
|
|
33
|
+
ctx.logger.info(`Auth routes registered at ${this.options.basePath}`);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
36
|
+
ctx.logger.error("Failed to register auth routes:", err);
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
ctx.logger.info("Auth Plugin started successfully");
|
|
41
|
+
}
|
|
42
|
+
async destroy() {
|
|
43
|
+
this.authManager = null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Register authentication routes with HTTP server
|
|
47
|
+
*/
|
|
48
|
+
registerAuthRoutes(httpServer, ctx) {
|
|
49
|
+
if (!this.authManager) return;
|
|
50
|
+
const basePath = this.options.basePath || "/api/v1/auth";
|
|
51
|
+
httpServer.post(`${basePath}/login`, async (req, res) => {
|
|
52
|
+
try {
|
|
53
|
+
const body = req.body;
|
|
54
|
+
const result = await this.authManager.login(body);
|
|
55
|
+
res.status(200).json(result);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
58
|
+
ctx.logger.error("Login error:", err);
|
|
59
|
+
res.status(401).json({
|
|
60
|
+
success: false,
|
|
61
|
+
error: err.message
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
httpServer.post(`${basePath}/register`, async (req, res) => {
|
|
66
|
+
try {
|
|
67
|
+
const body = req.body;
|
|
68
|
+
const result = await this.authManager.register(body);
|
|
69
|
+
res.status(201).json(result);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
72
|
+
ctx.logger.error("Registration error:", err);
|
|
73
|
+
res.status(400).json({
|
|
74
|
+
success: false,
|
|
75
|
+
error: err.message
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
httpServer.post(`${basePath}/logout`, async (req, res) => {
|
|
80
|
+
try {
|
|
81
|
+
const authHeader = req.headers["authorization"];
|
|
82
|
+
const token = typeof authHeader === "string" ? authHeader.replace("Bearer ", "") : void 0;
|
|
83
|
+
await this.authManager.logout(token);
|
|
84
|
+
res.status(200).json({ success: true });
|
|
85
|
+
} catch (error) {
|
|
86
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
87
|
+
ctx.logger.error("Logout error:", err);
|
|
88
|
+
res.status(400).json({
|
|
89
|
+
success: false,
|
|
90
|
+
error: err.message
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
httpServer.get(`${basePath}/session`, async (req, res) => {
|
|
95
|
+
try {
|
|
96
|
+
const authHeader = req.headers["authorization"];
|
|
97
|
+
const token = typeof authHeader === "string" ? authHeader.replace("Bearer ", "") : void 0;
|
|
98
|
+
const session = await this.authManager.getSession(token);
|
|
99
|
+
res.status(200).json({ success: true, data: session });
|
|
100
|
+
} catch (error) {
|
|
101
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
102
|
+
res.status(401).json({
|
|
103
|
+
success: false,
|
|
104
|
+
error: err.message
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
ctx.logger.debug("Auth routes registered:", {
|
|
109
|
+
basePath,
|
|
110
|
+
routes: [
|
|
111
|
+
`POST ${basePath}/login`,
|
|
112
|
+
`POST ${basePath}/register`,
|
|
113
|
+
`POST ${basePath}/logout`,
|
|
114
|
+
`GET ${basePath}/session`
|
|
115
|
+
]
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var AuthManager = class {
|
|
120
|
+
constructor(_config) {
|
|
121
|
+
}
|
|
122
|
+
async login(_credentials) {
|
|
123
|
+
throw new Error("Login not yet implemented");
|
|
124
|
+
}
|
|
125
|
+
async register(_userData) {
|
|
126
|
+
throw new Error("Registration not yet implemented");
|
|
127
|
+
}
|
|
128
|
+
async logout(_token) {
|
|
129
|
+
throw new Error("Logout not yet implemented");
|
|
130
|
+
}
|
|
131
|
+
async getSession(_token) {
|
|
132
|
+
throw new Error("Session retrieval not yet implemented");
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
export {
|
|
136
|
+
AuthPlugin
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { Plugin, PluginContext, IHttpServer } from '@objectstack/core';\nimport { AuthConfig } from '@objectstack/spec/system';\n\n/**\n * Auth Plugin Options\n * Extends AuthConfig from spec with additional runtime options\n */\nexport interface AuthPluginOptions extends Partial<AuthConfig> {\n /**\n * Whether to automatically register auth routes\n * @default true\n */\n registerRoutes?: boolean;\n \n /**\n * Base path for auth routes\n * @default '/api/v1/auth'\n */\n basePath?: string;\n}\n\n/**\n * Authentication Plugin\n * \n * Provides authentication and identity services for ObjectStack applications.\n * \n * Features:\n * - Session management\n * - User registration/login\n * - OAuth providers (Google, GitHub, etc.)\n * - Organization/team support\n * - 2FA, passkeys, magic links\n * \n * This plugin registers:\n * - `auth` service (auth manager instance)\n * - HTTP routes for authentication endpoints\n * \n * @planned This is a stub implementation. Full better-auth integration\n * will be added in a future version. For now, it provides the plugin\n * structure and basic route registration.\n */\nexport class AuthPlugin implements Plugin {\n name = 'com.objectstack.auth';\n type = 'standard';\n version = '1.0.0';\n dependencies = ['com.objectstack.server.hono']; // Requires HTTP server\n \n private options: AuthPluginOptions;\n private authManager: AuthManager | null = null;\n\n constructor(options: AuthPluginOptions = {}) {\n this.options = {\n registerRoutes: true,\n basePath: '/api/v1/auth',\n ...options\n };\n }\n\n async init(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Initializing Auth Plugin...');\n\n // Validate required configuration\n if (!this.options.secret) {\n throw new Error('AuthPlugin: secret is required');\n }\n\n // Initialize auth manager\n this.authManager = new AuthManager(this.options);\n\n // Register auth service\n ctx.registerService('auth', this.authManager);\n \n ctx.logger.info('Auth Plugin initialized successfully');\n }\n\n async start(ctx: PluginContext): Promise<void> {\n ctx.logger.info('Starting Auth Plugin...');\n\n if (!this.authManager) {\n throw new Error('Auth manager not initialized');\n }\n\n // Register HTTP routes if enabled\n if (this.options.registerRoutes) {\n try {\n const httpServer = ctx.getService<IHttpServer>('http-server');\n this.registerAuthRoutes(httpServer, ctx);\n ctx.logger.info(`Auth routes registered at ${this.options.basePath}`);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Failed to register auth routes:', err);\n throw err;\n }\n }\n\n ctx.logger.info('Auth Plugin started successfully');\n }\n\n async destroy(): Promise<void> {\n // Cleanup if needed\n this.authManager = null;\n }\n\n /**\n * Register authentication routes with HTTP server\n */\n private registerAuthRoutes(httpServer: IHttpServer, ctx: PluginContext): void {\n if (!this.authManager) return;\n\n const basePath = this.options.basePath || '/api/v1/auth';\n\n // Login endpoint\n httpServer.post(`${basePath}/login`, async (req, res) => {\n try {\n const body = req.body;\n const result = await this.authManager!.login(body);\n res.status(200).json(result);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Login error:', err);\n res.status(401).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n // Register endpoint\n httpServer.post(`${basePath}/register`, async (req, res) => {\n try {\n const body = req.body;\n const result = await this.authManager!.register(body);\n res.status(201).json(result);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Registration error:', err);\n res.status(400).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n // Logout endpoint\n httpServer.post(`${basePath}/logout`, async (req, res) => {\n try {\n const authHeader = req.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : undefined;\n await this.authManager!.logout(token);\n res.status(200).json({ success: true });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n ctx.logger.error('Logout error:', err);\n res.status(400).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n // Session endpoint\n httpServer.get(`${basePath}/session`, async (req, res) => {\n try {\n const authHeader = req.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : undefined;\n const session = await this.authManager!.getSession(token);\n res.status(200).json({ success: true, data: session });\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n res.status(401).json({\n success: false,\n error: err.message,\n });\n }\n });\n\n ctx.logger.debug('Auth routes registered:', {\n basePath,\n routes: [\n `POST ${basePath}/login`,\n `POST ${basePath}/register`,\n `POST ${basePath}/logout`,\n `GET ${basePath}/session`,\n ],\n });\n }\n}\n\n/**\n * Auth Manager\n * \n * @planned This is a stub implementation. Real authentication logic\n * will be implemented using better-auth or similar library in future versions.\n */\nclass AuthManager {\n constructor(_config: AuthPluginOptions) {\n // Store config for future use\n }\n\n async login(_credentials: any): Promise<any> {\n // @planned Implement actual login logic with better-auth\n throw new Error('Login not yet implemented');\n }\n\n async register(_userData: any): Promise<any> {\n // @planned Implement actual registration logic with better-auth\n throw new Error('Registration not yet implemented');\n }\n\n async logout(_token?: string): Promise<void> {\n // @planned Implement actual logout logic\n throw new Error('Logout not yet implemented');\n }\n\n async getSession(_token?: string): Promise<any> {\n // @planned Implement actual session retrieval\n throw new Error('Session retrieval not yet implemented');\n }\n}\n\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Auth Plugin Usage Example
|
|
5
|
+
*
|
|
6
|
+
* This example demonstrates how to use the AuthPlugin
|
|
7
|
+
* in an ObjectStack application.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { ObjectKernel } from '@objectstack/core';
|
|
11
|
+
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
|
|
12
|
+
import { AuthPlugin } from '@objectstack/plugin-auth';
|
|
13
|
+
|
|
14
|
+
// Create kernel with auth plugin
|
|
15
|
+
const kernel = new ObjectKernel({
|
|
16
|
+
plugins: [
|
|
17
|
+
// HTTP server is required for auth routes
|
|
18
|
+
new HonoServerPlugin({
|
|
19
|
+
port: 3000,
|
|
20
|
+
}),
|
|
21
|
+
|
|
22
|
+
// Auth plugin configuration
|
|
23
|
+
new AuthPlugin({
|
|
24
|
+
secret: process.env.AUTH_SECRET || 'your-secret-key-at-least-32-chars',
|
|
25
|
+
baseUrl: process.env.BASE_URL || 'http://localhost:3000',
|
|
26
|
+
databaseUrl: process.env.DATABASE_URL,
|
|
27
|
+
|
|
28
|
+
// OAuth providers (optional)
|
|
29
|
+
providers: [
|
|
30
|
+
{
|
|
31
|
+
id: 'google',
|
|
32
|
+
clientId: process.env.GOOGLE_CLIENT_ID || '',
|
|
33
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET || '',
|
|
34
|
+
scope: ['email', 'profile'],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'github',
|
|
38
|
+
clientId: process.env.GITHUB_CLIENT_ID || '',
|
|
39
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET || '',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
|
|
43
|
+
// Additional auth features (optional)
|
|
44
|
+
plugins: {
|
|
45
|
+
organization: true, // Multi-tenant support
|
|
46
|
+
twoFactor: true, // 2FA support
|
|
47
|
+
passkeys: false, // Passkey support
|
|
48
|
+
magicLink: true, // Magic link login
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// Session configuration (optional)
|
|
52
|
+
session: {
|
|
53
|
+
expiresIn: 60 * 60 * 24 * 7, // 7 days
|
|
54
|
+
updateAge: 60 * 60 * 24, // Update every 24 hours
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// Route configuration
|
|
58
|
+
registerRoutes: true,
|
|
59
|
+
basePath: '/api/v1/auth',
|
|
60
|
+
}),
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Initialize the kernel
|
|
65
|
+
async function main() {
|
|
66
|
+
try {
|
|
67
|
+
await kernel.init();
|
|
68
|
+
await kernel.start();
|
|
69
|
+
|
|
70
|
+
console.log('š Server started with auth plugin');
|
|
71
|
+
console.log('š Auth endpoints available at:');
|
|
72
|
+
console.log(' - POST http://localhost:3000/api/v1/auth/login');
|
|
73
|
+
console.log(' - POST http://localhost:3000/api/v1/auth/register');
|
|
74
|
+
console.log(' - POST http://localhost:3000/api/v1/auth/logout');
|
|
75
|
+
console.log(' - GET http://localhost:3000/api/v1/auth/session');
|
|
76
|
+
|
|
77
|
+
// Access the auth service from the kernel
|
|
78
|
+
const authService = kernel.getService('auth');
|
|
79
|
+
console.log('ā
Auth service registered:', !!authService);
|
|
80
|
+
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('ā Failed to start server:', error);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Handle graceful shutdown
|
|
88
|
+
process.on('SIGINT', async () => {
|
|
89
|
+
console.log('\nš Shutting down...');
|
|
90
|
+
await kernel.destroy();
|
|
91
|
+
process.exit(0);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Start the application
|
|
95
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@objectstack/plugin-auth",
|
|
3
|
+
"version": "2.0.2",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"description": "Authentication & Identity Plugin for ObjectStack",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@objectstack/core": "2.0.3",
|
|
10
|
+
"@objectstack/spec": "2.0.3"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@types/node": "^25.2.2",
|
|
14
|
+
"typescript": "^5.0.0",
|
|
15
|
+
"vitest": "^4.0.18"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"better-auth": "^1.0.0"
|
|
19
|
+
},
|
|
20
|
+
"peerDependenciesMeta": {
|
|
21
|
+
"better-auth": {
|
|
22
|
+
"optional": true
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup --config ../../../tsup.config.ts",
|
|
27
|
+
"test": "vitest run"
|
|
28
|
+
}
|
|
29
|
+
}
|