@maestro-js/init 1.0.0-alpha.24 → 1.0.0-alpha.4

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/bin.d.ts CHANGED
@@ -1,2 +1 @@
1
-
2
- export { }
1
+ #!/usr/bin/env node
package/dist/bin.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ #!/usr/bin/env node
2
3
  import {
3
4
  buildProjectTree,
4
- getInitVersion,
5
5
  scaffold
6
- } from "./chunk-FO3IYFDW.js";
6
+ } from "./chunk-P4YULL3I.js";
7
7
 
8
8
  // src/bin.ts
9
9
  import crypto from "crypto";
@@ -50,10 +50,10 @@ function deriveDbPort(name2) {
50
50
  }
51
51
  function installSkills(targetDir2) {
52
52
  const skillSources = [
53
- { cmd: `npx --yes @maestro-js/agent-skills@${getInitVersion()}`, label: "maestro" },
54
- { cmd: "npx skills add https://react-aria.adobe.com --skill react-aria -a claude-code -y", label: "react-aria" },
55
- { cmd: "npx skills add anthropics/skills --skill skill-creator -a claude-code -y", label: "skill-creator" },
56
- { cmd: "npx skills add mattpocock/skills --skill grill-me -a claude-code -y", label: "grill-me" },
53
+ { cmd: "npx --yes @maestro-js/agent-skills", label: "maestro" },
54
+ { cmd: "npx skills add https://react-aria.adobe.com --all", label: "react-aria" },
55
+ { cmd: "npx skills add anthropics/skills --skill skill-creator -y", label: "skill-creator" },
56
+ { cmd: "npx skills add mattpocock/skills --skill grill-me -y", label: "grill-me" },
57
57
  { cmd: "playwright-cli install --skills", label: "playwright-cli" }
58
58
  ];
59
59
  for (const { cmd, label } of skillSources) {
@@ -1,12 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // src/index.ts
4
- import fs from "fs";
5
- import path from "path";
6
- import { fileURLToPath } from "url";
7
-
8
3
  // src/templates/root.ts
9
- function rootPackageJson(name, maestroVersion) {
4
+ function rootPackageJson(name) {
10
5
  return JSON.stringify(
11
6
  {
12
7
  type: "module",
@@ -16,13 +11,13 @@ function rootPackageJson(name, maestroVersion) {
16
11
  "fks-restrict": "maestro config:run --config services -- node ./scripts/foreign-key-delete-behavior.ts restrict"
17
12
  },
18
13
  dependencies: {
19
- "@maestro-js/config": maestroVersion,
14
+ "@maestro-js/config": "latest",
20
15
  [`@${name}/services`]: "workspace:*"
21
16
  },
22
17
  devDependencies: {
23
- "@maestro-js/cli": maestroVersion,
24
- "@maestro-js/db-migrate": maestroVersion,
25
- "@maestro-js/db": maestroVersion,
18
+ "@maestro-js/cli": "latest",
19
+ "@maestro-js/db-migrate": "latest",
20
+ "@maestro-js/db": "latest",
26
21
  "@types/node": "^22.19.11",
27
22
  tsx: "^4.21.0"
28
23
  }
@@ -139,7 +134,7 @@ var dbMigrateConfig = `export default async function (env: Record<string, string
139
134
  `;
140
135
 
141
136
  // src/templates/schemas.ts
142
- function schemasPackageJson(name, maestroVersion) {
137
+ function schemasPackageJson(name) {
143
138
  return JSON.stringify(
144
139
  {
145
140
  name: `@${name}/schemas`,
@@ -150,7 +145,7 @@ function schemasPackageJson(name, maestroVersion) {
150
145
  dependencies: {
151
146
  "iso-fns": "npm:iso-fns@2.0.0-alpha.26",
152
147
  zod: "^4.3.0",
153
- "@maestro-js/iso-zod": maestroVersion
148
+ "@maestro-js/iso-zod": "latest"
154
149
  },
155
150
  devDependencies: {}
156
151
  },
@@ -163,7 +158,7 @@ var schemasIndex = `// Export your Zod schemas here
163
158
  `;
164
159
 
165
160
  // src/templates/services.ts
166
- function servicesPackageJson(name, maestroVersion) {
161
+ function servicesPackageJson(name) {
167
162
  return JSON.stringify(
168
163
  {
169
164
  name: `@${name}/services`,
@@ -177,29 +172,29 @@ function servicesPackageJson(name, maestroVersion) {
177
172
  dependencies: {
178
173
  [`@${name}/schemas`]: "workspace:*",
179
174
  "@aws-sdk/client-ses": "^3.1004.0",
180
- "@maestro-js/auth": maestroVersion,
181
- "@maestro-js/cache": maestroVersion,
182
- "@maestro-js/config": maestroVersion,
183
- "@maestro-js/crypt": maestroVersion,
184
- "@maestro-js/custom-errors": maestroVersion,
185
- "@maestro-js/db": maestroVersion,
186
- "@maestro-js/exceptions": maestroVersion,
187
- "@maestro-js/hash": maestroVersion,
188
- "@maestro-js/helpers": maestroVersion,
189
- "@maestro-js/iso-zod": maestroVersion,
190
- "@maestro-js/log": maestroVersion,
191
- "@maestro-js/mail": maestroVersion,
192
- "@maestro-js/password": maestroVersion,
193
- "@maestro-js/permissions": maestroVersion,
194
- "@maestro-js/queue": maestroVersion,
195
- "@maestro-js/rate-limiting": maestroVersion,
196
- "@maestro-js/recurring-jobs": maestroVersion,
197
- "@maestro-js/session": maestroVersion,
175
+ "@maestro-js/auth": "latest",
176
+ "@maestro-js/cache": "latest",
177
+ "@maestro-js/config": "latest",
178
+ "@maestro-js/crypt": "latest",
179
+ "@maestro-js/custom-errors": "latest",
180
+ "@maestro-js/db": "latest",
181
+ "@maestro-js/exceptions": "latest",
182
+ "@maestro-js/hash": "latest",
183
+ "@maestro-js/helpers": "latest",
184
+ "@maestro-js/iso-zod": "latest",
185
+ "@maestro-js/log": "latest",
186
+ "@maestro-js/mail": "latest",
187
+ "@maestro-js/password": "latest",
188
+ "@maestro-js/permissions": "latest",
189
+ "@maestro-js/queue": "latest",
190
+ "@maestro-js/rate-limiting": "latest",
191
+ "@maestro-js/recurring-jobs": "latest",
192
+ "@maestro-js/session": "latest",
198
193
  "iso-fns": "npm:iso-fns@2.0.0-alpha.26",
199
194
  zod: "^4.3.0"
200
195
  },
201
196
  devDependencies: {
202
- "@maestro-js/cli": maestroVersion,
197
+ "@maestro-js/cli": "latest",
203
198
  "@types/node": "^22.0.0",
204
199
  "beartest-js": "^8.0.2"
205
200
  }
@@ -384,7 +379,7 @@ export { CustomErrors } from '@maestro-js/custom-errors'
384
379
  `;
385
380
 
386
381
  // src/templates/web.ts
387
- function webPackageJson(name, maestroVersion) {
382
+ function webPackageJson(name) {
388
383
  return JSON.stringify(
389
384
  {
390
385
  name: `@${name}/${name}-web`,
@@ -402,9 +397,9 @@ function webPackageJson(name, maestroVersion) {
402
397
  dependencies: {
403
398
  [`@${name}/schemas`]: "workspace:*",
404
399
  [`@${name}/services`]: "workspace:*",
405
- "@maestro-js/custom-errors": maestroVersion,
406
- "@maestro-js/log": maestroVersion,
407
- "@maestro-js/form": maestroVersion,
400
+ "@maestro-js/custom-errors": "latest",
401
+ "@maestro-js/log": "latest",
402
+ "@maestro-js/form": "latest",
408
403
  "@react-router/node": "^7.9.0",
409
404
  "@react-router/serve": "^7.9.0",
410
405
  "@sentry/react-router": "^9",
@@ -419,8 +414,8 @@ function webPackageJson(name, maestroVersion) {
419
414
  zod: "^4.0.0"
420
415
  },
421
416
  devDependencies: {
422
- "@maestro-js/cli": maestroVersion,
423
- "@maestro-js/react-router-file-routes": maestroVersion,
417
+ "@maestro-js/cli": "latest",
418
+ "@maestro-js/react-router-file-routes": "latest",
424
419
  "@playwright/test": "^1.52.0",
425
420
  "@react-router/dev": "^7.9.0",
426
421
  "@tailwindcss/vite": "^4.2.0",
@@ -909,93 +904,34 @@ export function getRequestContext(context: Readonly<RouterContextProvider>) {
909
904
  return request
910
905
  }
911
906
  `;
912
- var csrfMiddlewareServer = `import { timingSafeEqual } from 'node:crypto'
913
- import type { MiddlewareFunction } from 'react-router'
907
+ var csrfMiddlewareServer = `import type { MiddlewareFunction } from 'react-router'
914
908
  import { getRequestContext } from './request-context.server'
915
909
 
916
- const MUTATING_METHODS = new Set(['POST', 'PUT', 'PATCH', 'DELETE'])
917
-
918
910
  export const csrfMiddleware: MiddlewareFunction<Response> = async ({ request, context }, next) => {
919
- if (!MUTATING_METHODS.has(request.method)) {
920
- return next()
921
- }
922
-
923
- // Routes accepting JSON or other non-form bodies use an X-CSRF-Token header
924
- // instead of a hidden form field. Either way, never throw 500 from this
925
- // middleware on a malformed body \u2014 return a clean 403.
926
- const contentType = request.headers.get('content-type') ?? ''
927
- let clientCsrfToken: string | null = null
928
- if (contentType.startsWith('application/x-www-form-urlencoded') || contentType.startsWith('multipart/form-data')) {
929
- try {
930
- const cloned = request.clone()
931
- const formData = await cloned.formData()
932
- const value = formData.get('__csrfToken')
933
- clientCsrfToken = typeof value === 'string' ? value : null
934
- } catch {
935
- clientCsrfToken = null
911
+ const mutatingMethods = ['POST', 'PUT', 'DELETE']
912
+ if (mutatingMethods.includes(request.method)) {
913
+ const cloned = request.clone()
914
+ const formDataForMiddleware = await cloned.formData()
915
+ const clientCsrfToken = formDataForMiddleware.get('__csrfToken')
916
+ const requestContext = getRequestContext(context)
917
+ const sessionCsrfToken = requestContext.session.getCsrfToken()
918
+ if (clientCsrfToken !== sessionCsrfToken) {
919
+ throw new Response('Invalid CSRF token', { status: 403 })
936
920
  }
937
- } else {
938
- clientCsrfToken = request.headers.get('x-csrf-token')
939
- }
940
-
941
- const requestContext = getRequestContext(context)
942
- const sessionCsrfToken = requestContext.session.getCsrfToken()
943
-
944
- if (!clientCsrfToken || !constantTimeEqual(clientCsrfToken, sessionCsrfToken)) {
945
- throw new Response('Invalid CSRF token', { status: 403 })
946
921
  }
947
922
  return next()
948
923
  }
949
-
950
- function constantTimeEqual(a: string, b: string): boolean {
951
- const aBuf = Buffer.from(a)
952
- const bBuf = Buffer.from(b)
953
- if (aBuf.length !== bBuf.length) return false
954
- return timingSafeEqual(aBuf, bBuf)
955
- }
956
924
  `;
957
925
  var securityHeadersMiddlewareServer = `import type { MiddlewareFunction } from 'react-router'
958
926
 
959
- // Security-headers middleware must be the OUTERMOST middleware so that headers
960
- // are applied to thrown Responses (e.g. 403s from csrfMiddleware) as well as
961
- // returned ones \u2014 try/finally ensures both code paths get the headers.
962
927
  export const securityHeadersMiddleware: MiddlewareFunction<Response> = async (_args, next) => {
963
- let response: Response
964
- try {
965
- response = await next()
966
- } catch (thrown) {
967
- if (thrown instanceof Response) {
968
- applySecurityHeaders(thrown.headers)
969
- }
970
- throw thrown
971
- }
972
- applySecurityHeaders(response.headers)
928
+ const response = await next()
929
+ response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')
930
+ response.headers.set('X-Content-Type-Options', 'nosniff')
931
+ response.headers.set('X-Frame-Options', 'DENY')
932
+ response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
973
933
  return response
974
934
  }
975
-
976
- function applySecurityHeaders(headers: Headers) {
977
- headers.set('Strict-Transport-Security', 'max-age=63072000; includeSubDomains; preload')
978
- headers.set('X-Content-Type-Options', 'nosniff')
979
- headers.set('X-Frame-Options', 'DENY')
980
- headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
981
- // Default-deny CSP. Tighten with route-level nonces for inline <script>/<style>.
982
- // Apps that need third-party origins (analytics, fonts, CDNs) should extend
983
- // this list \u2014 ship something restrictive by default rather than leaving it
984
- // off entirely.
985
- if (!headers.has('Content-Security-Policy')) {
986
- headers.set(
987
- 'Content-Security-Policy',
988
- "default-src 'self'; img-src 'self' data: https:; style-src 'self' 'unsafe-inline'; " +
989
- "script-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"
990
- )
991
- }
992
- headers.set(
993
- 'Permissions-Policy',
994
- 'camera=(), microphone=(), geolocation=(), payment=(), usb=(), accelerometer=(), gyroscope=(), magnetometer=()'
995
- )
996
- headers.set('Cross-Origin-Opener-Policy', 'same-origin')
997
- headers.set('Cross-Origin-Resource-Policy', 'same-origin')
998
- }
999
935
  `;
1000
936
  var customErrorStatusCodeMiddlewareServer = `import * as Sentry from '@sentry/react-router'
1001
937
  import { type MiddlewareFunction } from 'react-router'
@@ -1047,7 +983,7 @@ export function getSessionToast(session: Session): Toast | null {
1047
983
  `;
1048
984
 
1049
985
  // src/templates/queue-processor.ts
1050
- function queueProcessorPackageJson(name, maestroVersion) {
986
+ function queueProcessorPackageJson(name) {
1051
987
  return JSON.stringify(
1052
988
  {
1053
989
  name: `@${name}/queue-processor`,
@@ -1057,11 +993,11 @@ function queueProcessorPackageJson(name, maestroVersion) {
1057
993
  start: "maestro config:run --config queue-processor -- tsx src/index.ts"
1058
994
  },
1059
995
  dependencies: {
1060
- "@maestro-js/config": maestroVersion,
996
+ "@maestro-js/config": "latest",
1061
997
  [`@${name}/services`]: "workspace:*"
1062
998
  },
1063
999
  devDependencies: {
1064
- "@maestro-js/cli": maestroVersion,
1000
+ "@maestro-js/cli": "latest",
1065
1001
  "@types/node": "^22.19.11",
1066
1002
  tsx: "^4.21.0"
1067
1003
  }
@@ -1254,16 +1190,9 @@ function replaceTokens(content, tokens) {
1254
1190
  }
1255
1191
 
1256
1192
  // src/index.ts
1257
- function getInitVersion() {
1258
- const dir = path.dirname(fileURLToPath(import.meta.url));
1259
- const raw = fs.readFileSync(path.join(dir, "../package.json"), "utf-8");
1260
- const pkg = JSON.parse(raw);
1261
- return pkg.version;
1262
- }
1263
1193
  function buildProjectTree(name) {
1264
- const maestroVersion = `^${getInitVersion()}`;
1265
1194
  return {
1266
- "package.json": rootPackageJson(name, maestroVersion),
1195
+ "package.json": rootPackageJson(name),
1267
1196
  "pnpm-workspace.yaml": pnpmWorkspace(name),
1268
1197
  "tsconfig.json": rootTsconfig,
1269
1198
  ".env": rootEnv,
@@ -1276,13 +1205,13 @@ function buildProjectTree(name) {
1276
1205
  },
1277
1206
  packages: {
1278
1207
  schemas: {
1279
- "package.json": schemasPackageJson(name, maestroVersion),
1208
+ "package.json": schemasPackageJson(name),
1280
1209
  src: {
1281
1210
  "index.ts": schemasIndex
1282
1211
  }
1283
1212
  },
1284
1213
  services: {
1285
- "package.json": servicesPackageJson(name, maestroVersion),
1214
+ "package.json": servicesPackageJson(name),
1286
1215
  "tsconfig.json": servicesTsconfig,
1287
1216
  src: {
1288
1217
  "maestro.ts": maestroTs,
@@ -1291,7 +1220,7 @@ function buildProjectTree(name) {
1291
1220
  }
1292
1221
  },
1293
1222
  [`${name}-web`]: {
1294
- "package.json": webPackageJson(name, maestroVersion),
1223
+ "package.json": webPackageJson(name),
1295
1224
  "tsconfig.json": webTsconfig,
1296
1225
  "vite.config.ts": viteConfig,
1297
1226
  "react-router.config.ts": reactRouterConfig,
@@ -1320,7 +1249,7 @@ function buildProjectTree(name) {
1320
1249
  }
1321
1250
  },
1322
1251
  "queue-processor": {
1323
- "package.json": queueProcessorPackageJson(name, maestroVersion),
1252
+ "package.json": queueProcessorPackageJson(name),
1324
1253
  "tsconfig.json": queueProcessorTsconfig,
1325
1254
  src: {
1326
1255
  "index.ts": queueProcessorIndex,
@@ -1342,6 +1271,5 @@ function buildProjectTree(name) {
1342
1271
 
1343
1272
  export {
1344
1273
  scaffold,
1345
- getInitVersion,
1346
1274
  buildProjectTree
1347
1275
  };
package/dist/index.d.ts CHANGED
@@ -4,7 +4,6 @@ type Tree = {
4
4
  type Tokens = Record<string, string>;
5
5
  declare function scaffold(tree: Tree, basePath: string, tokens?: Tokens): Promise<string[]>;
6
6
 
7
- declare function getInitVersion(): string;
8
7
  declare function buildProjectTree(name: string): Tree;
9
8
 
10
- export { type Tokens, type Tree, buildProjectTree, getInitVersion, scaffold };
9
+ export { type Tokens, type Tree, buildProjectTree, scaffold };
package/dist/index.js CHANGED
@@ -1,11 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  buildProjectTree,
4
- getInitVersion,
5
4
  scaffold
6
- } from "./chunk-FO3IYFDW.js";
5
+ } from "./chunk-P4YULL3I.js";
7
6
  export {
8
7
  buildProjectTree,
9
- getInitVersion,
10
8
  scaffold
11
9
  };
package/package.json CHANGED
@@ -14,9 +14,9 @@
14
14
  "devDependencies": {
15
15
  "@types/node": "^22.19.11"
16
16
  },
17
- "version": "1.0.0-alpha.24",
17
+ "version": "1.0.0-alpha.4",
18
18
  "publishConfig": {
19
- "access": "public"
19
+ "access": "restricted"
20
20
  },
21
21
  "files": [
22
22
  "dist"