@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/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
+ }