@lastshotlabs/bunshot 0.0.28 → 0.1.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.
@@ -35,5 +35,5 @@
35
35
  ]
36
36
  }
37
37
  },
38
- "version": "0.0.28"
38
+ "version": "0.1.0"
39
39
  }
package/dist/cli/index.js CHANGED
File without changes
@@ -200,21 +200,11 @@ export function createCredentialStuffingService(config, repo) {
200
200
  const ipWindowMs = config.maxAccountsPerIp?.windowMs ?? 15 * 60 * 1000;
201
201
  const accountWindowMs = config.maxIpsPerAccount?.windowMs ?? 15 * 60 * 1000;
202
202
  const ipCount = await repo.getSetSize(`ip:${ip}`, ipWindowMs);
203
- if (ipCount >= ipMax) {
204
- try {
205
- config.onDetected?.({ type: 'ip', key: ip, count: ipCount });
206
- }
207
- catch { }
203
+ if (ipCount >= ipMax)
208
204
  return true;
209
- }
210
205
  const accountCount = await repo.getSetSize(`account:${identifier}`, accountWindowMs);
211
- if (accountCount >= accountMax) {
212
- try {
213
- config.onDetected?.({ type: 'account', key: identifier, count: accountCount });
214
- }
215
- catch { }
206
+ if (accountCount >= accountMax)
216
207
  return true;
217
- }
218
208
  return false;
219
209
  },
220
210
  };
@@ -17,14 +17,17 @@ export function createAuthPlugin(rawConfig) {
17
17
  const config = validatePluginConfig('bunshot-auth', rawConfig, authPluginConfigSchema);
18
18
  // Lifecycle handoff: setupMiddleware resolves this promise once bootstrap
19
19
  // completes. Later phases await it — type-safe, no mutable variable.
20
- // rejectBootstrap is called when setupMiddleware throws so that downstream
21
- // phases fail immediately instead of deadlocking.
20
+ // rejectBootstrap is called when setupMiddleware throws so teardown() can
21
+ // detect failure and return early rather than deadlocking on bootstrapReady.
22
+ // The .catch(() => {}) suppresses the unhandled-rejection warning in cases
23
+ // where setupMiddleware throws before teardown() attaches its own catch.
22
24
  let resolveBootstrap;
23
25
  let rejectBootstrap;
24
26
  const bootstrapReady = new Promise((resolve, reject) => {
25
27
  resolveBootstrap = resolve;
26
28
  rejectBootstrap = reject;
27
29
  });
30
+ bootstrapReady.catch(() => { });
28
31
  return {
29
32
  name: 'bunshot-auth',
30
33
  async setupMiddleware(app, frameworkConfig, bus) {
@@ -49,7 +49,7 @@ function createMemoryAuditLogProvider() {
49
49
  const memoryLogs = [];
50
50
  let evictedEntries = 0;
51
51
  let hasWarnedAboutTruncation = false;
52
- console.warn(`[bunshot] Memory adapter for audit log is capped at ${DEFAULT_MAX_ENTRIES} entries and has no TTL-based eviction - for development/testing only`);
52
+ console.warn(`[bunshot] Memory adapter for audit log is capped at ${DEFAULT_MAX_ENTRIES} entries and has no eviction for development/testing only`);
53
53
  return {
54
54
  async logEntry(entry) {
55
55
  try {
@@ -3,27 +3,44 @@ import { createQueueFactory } from '../lib/queue';
3
3
  // Implementation
4
4
  // ---------------------------------------------------------------------------
5
5
  export async function mountOptionalEndpoints(app, coreRoutesDir, jobs, metrics, upload, metricsState, resolvedSecrets) {
6
+ // Security validation runs before infrastructure creation so config errors
7
+ // take priority over missing infrastructure (Redis) errors.
8
+ if (jobs?.statusEndpoint) {
9
+ const jobsAuth = jobs.auth ?? 'none';
10
+ if (jobsAuth === 'none' && !jobs.unsafePublic) {
11
+ if (process.env.NODE_ENV === 'production') {
12
+ throw new Error('[security] jobs.auth is required in production. Set jobs.auth or explicitly set unsafePublic: true with auth: "none".');
13
+ }
14
+ console.warn('[security] /jobs is enabled without auth. Configure jobs.auth for production.');
15
+ }
16
+ }
17
+ // Queue factory is created lazily — defers Redis validation to first use
18
+ // so the app can start without Redis when using the jobs/metrics endpoints.
6
19
  const needsQueueFactory = !!jobs?.statusEndpoint || !!metrics?.queues?.length;
7
- const queueFactory = needsQueueFactory
8
- ? (() => {
20
+ let _cachedFactory;
21
+ function getLazyFactory() {
22
+ if (!_cachedFactory) {
9
23
  if (!resolvedSecrets.redisHost) {
10
24
  throw new Error('[queue] Jobs/metrics queue helpers require REDIS_HOST via the Bunshot secret bundle at startup.');
11
25
  }
12
- return createQueueFactory({
26
+ _cachedFactory = createQueueFactory({
13
27
  host: resolvedSecrets.redisHost,
14
28
  user: resolvedSecrets.redisUser,
15
29
  password: resolvedSecrets.redisPassword,
16
30
  });
17
- })()
31
+ }
32
+ return _cachedFactory;
33
+ }
34
+ const queueFactory = needsQueueFactory
35
+ ? {
36
+ createQueue: (...args) => getLazyFactory().createQueue(...args),
37
+ createWorker: (...args) => getLazyFactory().createWorker(...args),
38
+ createCronWorker: (...args) => getLazyFactory().createCronWorker(...args),
39
+ cleanupStaleSchedulers: (...args) => getLazyFactory().cleanupStaleSchedulers(...args),
40
+ createDLQHandler: (...args) => getLazyFactory().createDLQHandler(...args),
41
+ }
18
42
  : undefined;
19
43
  if (jobs?.statusEndpoint) {
20
- const jobsAuth = jobs.auth ?? 'none';
21
- if (jobsAuth === 'none' && !jobs.unsafePublic) {
22
- if (process.env.NODE_ENV === 'production') {
23
- throw new Error('[security] jobs.auth is required in production. Set jobs.auth or explicitly set unsafePublic: true with auth: "none".');
24
- }
25
- console.warn('[security] /jobs is enabled without auth. Configure jobs.auth for production.');
26
- }
27
44
  const { createJobsRouter } = await import(`${coreRoutesDir}/jobs`);
28
45
  app.route('/', createJobsRouter(jobs, queueFactory));
29
46
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "workspaces": [
4
4
  "packages/*"
5
5
  ],
6
- "version": "0.0.28",
6
+ "version": "0.1.0",
7
7
  "description": "Batteries-included Bun + Hono API framework — auth, sessions, rate limiting, WebSocket, queues, and OpenAPI docs out of the box",
8
8
  "repository": {
9
9
  "type": "git",
@@ -60,11 +60,15 @@
60
60
  "topicSeparator": " "
61
61
  },
62
62
  "scripts": {
63
- "typecheck": "bun --filter '*' run typecheck",
63
+ "typecheck": "bun run --filter '*' typecheck",
64
64
  "typecheck:root": "tsc --noEmit",
65
65
  "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && tsup --config tsup.cli.config.ts && oclif manifest",
66
+ "build:packages": "bun run --filter '*' build",
66
67
  "prepublishOnly": "bun run build",
67
- "release": "npm version patch && npm publish",
68
+ "release": "bun run build && bun publish --access public && bun run --filter '*' publish",
69
+ "release:patch": "bun run --filter '*' version patch && npm version patch && bun run release",
70
+ "release:minor": "bun run --filter '*' version minor && npm version minor && bun run release",
71
+ "release:major": "bun run --filter '*' version major && npm version major && bun run release",
68
72
  "dev": "bun --watch src/index.ts",
69
73
  "start": "bun src/index.ts",
70
74
  "test": "bun test tests/unit tests/integration && bun run test:isolated && bun test --config packages/bunshot-core/bunfig.toml packages/bunshot-core/tests && bun test --config packages/bunshot-permissions/bunfig.toml packages/bunshot-permissions/tests",
@@ -92,8 +96,8 @@
92
96
  "dependencies": {
93
97
  "@asteasolutions/zod-to-openapi": "^8.4.1",
94
98
  "@hono/zod-openapi": "1.2.2",
95
- "@lastshotlabs/bunshot-auth": "0.1.0",
96
- "@lastshotlabs/bunshot-core": "0.1.0",
99
+ "@lastshotlabs/bunshot-auth": "workspace:*",
100
+ "@lastshotlabs/bunshot-core": "workspace:*",
97
101
  "@oclif/core": "^4.10.2",
98
102
  "@scalar/hono-api-reference": "0.10.0",
99
103
  "arctic": "^3.7.0",
@@ -110,7 +114,15 @@
110
114
  "@simplewebauthn/server": ">=10.0.0",
111
115
  "@aws-sdk/client-s3": ">=3.0",
112
116
  "@aws-sdk/s3-request-presigner": ">=3.0",
113
- "@aws-sdk/lib-storage": ">=3.0"
117
+ "@aws-sdk/lib-storage": ">=3.0",
118
+ "@lastshotlabs/bunshot-admin": ">=0.1.0",
119
+ "@lastshotlabs/bunshot-bullmq": ">=0.1.0",
120
+ "@lastshotlabs/bunshot-community": ">=0.1.0",
121
+ "@lastshotlabs/bunshot-mail": ">=0.0.1",
122
+ "@lastshotlabs/bunshot-permissions": ">=0.1.0",
123
+ "@lastshotlabs/bunshot-postgres": ">=0.1.0",
124
+ "@lastshotlabs/bunshot-push": ">=0.1.0",
125
+ "@lastshotlabs/bunshot-webhooks": ">=0.0.1"
114
126
  },
115
127
  "peerDependenciesMeta": {
116
128
  "mongoose": {
@@ -136,9 +148,35 @@
136
148
  },
137
149
  "@aws-sdk/lib-storage": {
138
150
  "optional": true
151
+ },
152
+ "@lastshotlabs/bunshot-admin": {
153
+ "optional": true
154
+ },
155
+ "@lastshotlabs/bunshot-bullmq": {
156
+ "optional": true
157
+ },
158
+ "@lastshotlabs/bunshot-community": {
159
+ "optional": true
160
+ },
161
+ "@lastshotlabs/bunshot-mail": {
162
+ "optional": true
163
+ },
164
+ "@lastshotlabs/bunshot-permissions": {
165
+ "optional": true
166
+ },
167
+ "@lastshotlabs/bunshot-postgres": {
168
+ "optional": true
169
+ },
170
+ "@lastshotlabs/bunshot-push": {
171
+ "optional": true
172
+ },
173
+ "@lastshotlabs/bunshot-webhooks": {
174
+ "optional": true
139
175
  }
140
176
  },
141
177
  "devDependencies": {
178
+ "@aws-sdk/client-sesv2": "^3.1017.0",
179
+ "@react-email/render": "^2.0.4",
142
180
  "@simplewebauthn/server": "^13.1.1",
143
181
  "@trivago/prettier-plugin-sort-imports": "^6.0.2",
144
182
  "@types/bun": "1.3.10",