@memberjunction/server-bootstrap 0.0.1 → 3.0.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 CHANGED
@@ -1,45 +1,162 @@
1
1
  # @memberjunction/server-bootstrap
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
3
+ MemberJunction 3.0 Server Bootstrap - Encapsulates all server initialization logic into a single, simple function.
4
4
 
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
5
+ ## Overview
6
+
7
+ In MemberJunction 3.0, server applications (MJAPI) become **minimal bootstrapping files** (~6 lines of code) that import all functionality from NPM packages. This package provides the `createMJServer()` function that handles all the complex initialization logic.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @memberjunction/server-bootstrap
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Basic Usage (Minimal MJAPI 3.0)
18
+
19
+ Create your `packages/api/src/index.ts`:
6
20
 
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
21
+ ```typescript
22
+ import { createMJServer } from '@memberjunction/server-bootstrap';
8
23
 
9
- ## Purpose
24
+ // Import generated packages to trigger registration
25
+ import '@mycompany/generated-entities';
26
+ import '@mycompany/generated-actions';
27
+ import '@mycompany/generated-resolvers';
10
28
 
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@memberjunction/server-bootstrap`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
29
+ createMJServer().catch(console.error);
30
+ ```
15
31
 
16
- ## What is OIDC Trusted Publishing?
32
+ **That's it!** Your entire MJAPI application in 6 lines.
17
33
 
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
34
+ ### With Custom Configuration
19
35
 
20
- ## Setup Instructions
36
+ ```typescript
37
+ import { createMJServer } from '@memberjunction/server-bootstrap';
21
38
 
22
- To properly configure OIDC trusted publishing for this package:
39
+ createMJServer({
40
+ // Add custom resolver paths
41
+ resolverPaths: ['./custom-resolvers/**/*Resolver.{js,ts}'],
23
42
 
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
43
+ // Run custom logic before server starts
44
+ beforeStart: async () => {
45
+ console.log('Initializing custom services...');
46
+ // Your initialization code here
47
+ },
28
48
 
29
- ## DO NOT USE THIS PACKAGE
49
+ // Run custom logic after server starts
50
+ afterStart: async () => {
51
+ console.log('Server is ready!');
52
+ // Your post-startup code here
53
+ },
30
54
 
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
55
+ // Configure REST API
56
+ restApiOptions: {
57
+ enabled: true,
58
+ includeEntities: ['Users', 'Companies'],
59
+ excludeEntities: ['SystemSettings']
60
+ }
61
+ }).catch(console.error);
62
+ ```
36
63
 
37
- ## More Information
64
+ ## What It Does
38
65
 
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
66
+ The `createMJServer()` function handles:
42
67
 
43
- ---
68
+ 1. **Configuration Loading** - Automatically finds and loads `mj.config.cjs` or `.mjrc`
69
+ 2. **Generated Package Discovery** - Auto-imports generated entities, actions, forms, and resolvers
70
+ 3. **Database Connection** - Sets up connection pooling with configured credentials
71
+ 4. **GraphQL Schema Building** - Discovers resolvers and builds the GraphQL schema
72
+ 5. **WebSocket Setup** - Configures WebSocket support for GraphQL subscriptions
73
+ 6. **REST API Setup** - Registers REST endpoints based on configuration
74
+ 7. **Graceful Shutdown** - Handles SIGTERM/SIGINT signals properly
75
+ 8. **Scheduled Jobs** - Initializes and starts scheduled job service if enabled
44
76
 
45
- **Maintained for OIDC setup purposes only**
77
+ ## Configuration
78
+
79
+ The function uses your `mj.config.cjs` for all database and server settings:
80
+
81
+ ```javascript
82
+ // mj.config.cjs
83
+ module.exports = {
84
+ dbHost: process.env.DB_HOST,
85
+ dbPort: process.env.DB_PORT || 1433,
86
+ dbDatabase: process.env.DB_DATABASE,
87
+ dbUsername: process.env.DB_USERNAME,
88
+ dbPassword: process.env.DB_PASSWORD,
89
+
90
+ graphqlPort: process.env.PORT || 4000,
91
+
92
+ // 3.0 Code Generation Configuration
93
+ codeGeneration: {
94
+ outputMode: 'packages',
95
+ packageScope: '@mycompany',
96
+ packages: {
97
+ entities: {
98
+ path: './packages/generated-entities',
99
+ name: '@mycompany/generated-entities'
100
+ },
101
+ actions: {
102
+ path: './packages/generated-actions',
103
+ name: '@mycompany/generated-actions'
104
+ },
105
+ graphqlResolvers: {
106
+ path: './packages/generated-resolvers',
107
+ name: '@mycompany/generated-resolvers'
108
+ }
109
+ }
110
+ }
111
+ };
112
+ ```
113
+
114
+ ## API Reference
115
+
116
+ ### `createMJServer(options?: MJServerConfig): Promise<void>`
117
+
118
+ Creates and starts a MemberJunction API server.
119
+
120
+ #### Parameters
121
+
122
+ - `options.configPath` - Path to config file (optional, auto-discovers if not provided)
123
+ - `options.resolverPaths` - Additional resolver paths beyond defaults
124
+ - `options.beforeStart` - Hook function to run before server starts
125
+ - `options.afterStart` - Hook function to run after server starts
126
+ - `options.restApiOptions` - REST API configuration options
127
+
128
+ #### Returns
129
+
130
+ Promise that resolves when the server is running.
131
+
132
+ ## Migration from 2.x
133
+
134
+ In MemberJunction 2.x, your MJAPI/src/index.ts had ~34 lines of boilerplate code for database setup, schema building, etc.
135
+
136
+ **Before (2.x):**
137
+ ```typescript
138
+ // 34 lines of configuration, pool setup, schema building, etc.
139
+ import { serve } from '@memberjunction/server';
140
+ // ... lots of setup code ...
141
+ await serve(resolverPaths);
142
+ ```
143
+
144
+ **After (3.0):**
145
+ ```typescript
146
+ import { createMJServer } from '@memberjunction/server-bootstrap';
147
+ createMJServer().catch(console.error);
148
+ ```
149
+
150
+ All the complexity is now encapsulated in this package and updated via NPM.
151
+
152
+ ## Benefits
153
+
154
+ - **Zero-copy updates** - `npm update` brings all improvements automatically
155
+ - **No stale code** - Bootstrap logic stays up-to-date with MJ releases
156
+ - **Minimal surface area** - Fewer lines of code means fewer places for bugs
157
+ - **Standard patterns** - Everyone uses the same initialization flow
158
+ - **Extensible** - Hooks allow custom logic without modifying core
159
+
160
+ ## License
161
+
162
+ MIT
@@ -0,0 +1,11 @@
1
+ import { MJServerOptions } from '@memberjunction/server';
2
+ export interface MJServerConfig {
3
+ configPath?: string;
4
+ resolverPaths?: string[];
5
+ beforeStart?: () => void | Promise<void>;
6
+ afterStart?: () => void | Promise<void>;
7
+ restApiOptions?: MJServerOptions['restApiOptions'];
8
+ }
9
+ export declare function createMJServer(options?: MJServerConfig): Promise<void>;
10
+ export type { MJServerOptions } from '@memberjunction/server';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAS,eAAe,EAAc,MAAM,wBAAwB,CAAC;AAM5E,MAAM,WAAW,cAAc;IAI7B,UAAU,CAAC,EAAE,MAAM,CAAC;IAMpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAKzB,WAAW,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAKzC,UAAU,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAKxC,cAAc,CAAC,EAAE,eAAe,CAAC,gBAAgB,CAAC,CAAC;CACpD;AA+ED,wBAAsB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DhF;AAGD,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,62 @@
1
+ import { serve } from '@memberjunction/server';
2
+ import { cosmiconfigSync } from 'cosmiconfig';
3
+ async function discoverAndLoadGeneratedPackages(configResult) {
4
+ if (!configResult?.config?.codeGeneration?.packages) {
5
+ console.warn('No codeGeneration.packages configuration found - skipping auto-import of generated packages');
6
+ return;
7
+ }
8
+ const packages = configResult.config.codeGeneration.packages;
9
+ const packageTypes = ['entities', 'actions', 'angularForms', 'graphqlResolvers'];
10
+ for (const pkgType of packageTypes) {
11
+ if (packages[pkgType]?.name) {
12
+ const pkgName = packages[pkgType].name;
13
+ try {
14
+ await import(pkgName);
15
+ console.log(`✓ Loaded generated package: ${pkgName}`);
16
+ }
17
+ catch (error) {
18
+ if (error.code === 'ERR_MODULE_NOT_FOUND') {
19
+ console.log(`ℹ Generated package not found (may not exist yet): ${pkgName}`);
20
+ }
21
+ else {
22
+ console.warn(`⚠ Error loading generated package ${pkgName}:`, error);
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ export async function createMJServer(options = {}) {
29
+ console.log('🚀 MemberJunction 3.0 Server Bootstrap');
30
+ console.log('=====================================\n');
31
+ console.log('');
32
+ const explorer = cosmiconfigSync('mj', { searchStrategy: 'global' });
33
+ const configSearchResult = explorer.search(options.configPath || process.cwd());
34
+ const configResult = {
35
+ config: configSearchResult?.config || {},
36
+ hasUserConfig: configSearchResult && !configSearchResult.isEmpty,
37
+ configFilePath: configSearchResult?.filepath
38
+ };
39
+ console.log('Loading generated packages...');
40
+ await discoverAndLoadGeneratedPackages(configResult);
41
+ console.log('');
42
+ const resolverPaths = options.resolverPaths || [
43
+ './src/generated/generated.{js,ts}',
44
+ './dist/generated/generated.{js,ts}',
45
+ './generated/generated.{js,ts}',
46
+ ];
47
+ if (options.beforeStart) {
48
+ console.log('Running pre-start hook...');
49
+ await Promise.resolve(options.beforeStart());
50
+ console.log('');
51
+ }
52
+ const serverOptions = {
53
+ onBeforeServe: options.beforeStart,
54
+ restApiOptions: options.restApiOptions
55
+ };
56
+ console.log('Starting MemberJunction Server...\n');
57
+ await serve(resolverPaths, undefined, serverOptions);
58
+ if (options.afterStart) {
59
+ await Promise.resolve(options.afterStart());
60
+ }
61
+ }
62
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,32 @@
1
1
  {
2
2
  "name": "@memberjunction/server-bootstrap",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @memberjunction/server-bootstrap",
3
+ "version": "3.0.0",
4
+ "description": "MemberJunction Server Bootstrap - Encapsulates all server initialization logic",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "watch": "tsc --watch",
11
+ "clean": "rm -rf dist"
12
+ },
5
13
  "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
14
+ "memberjunction",
15
+ "bootstrap",
16
+ "server"
17
+ ],
18
+ "author": "MemberJunction",
19
+ "license": "MIT",
20
+ "dependencies": {
21
+ "@memberjunction/core": "3.0.0",
22
+ "@memberjunction/server": "3.0.0",
23
+ "cosmiconfig": "^9.0.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^22.10.2",
27
+ "typescript": "^5.4.5"
28
+ },
29
+ "files": [
30
+ "dist/**/*"
9
31
  ]
10
32
  }