@mars-stack/core 0.4.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.
Files changed (192) hide show
  1. package/README.md +32 -0
  2. package/cursor/manifest.json +304 -0
  3. package/cursor/rules/mars-composition-patterns.mdc +186 -0
  4. package/cursor/rules/mars-data-access.mdc +26 -0
  5. package/cursor/rules/mars-project-structure.mdc +34 -0
  6. package/cursor/rules/mars-security.mdc +25 -0
  7. package/cursor/rules/mars-testing.mdc +24 -0
  8. package/cursor/rules/mars-ui-conventions.mdc +29 -0
  9. package/cursor/skills/mars-add-api-route/SKILL.md +120 -0
  10. package/cursor/skills/mars-add-audit-log/SKILL.md +373 -0
  11. package/cursor/skills/mars-add-blog/SKILL.md +447 -0
  12. package/cursor/skills/mars-add-command-palette/SKILL.md +438 -0
  13. package/cursor/skills/mars-add-component/SKILL.md +158 -0
  14. package/cursor/skills/mars-add-crud-routes/SKILL.md +221 -0
  15. package/cursor/skills/mars-add-e2e-test/SKILL.md +227 -0
  16. package/cursor/skills/mars-add-error-boundary/SKILL.md +472 -0
  17. package/cursor/skills/mars-add-feature/SKILL.md +174 -0
  18. package/cursor/skills/mars-add-middleware/SKILL.md +135 -0
  19. package/cursor/skills/mars-add-page/SKILL.md +153 -0
  20. package/cursor/skills/mars-add-prisma-model/SKILL.md +148 -0
  21. package/cursor/skills/mars-add-protected-resource/SKILL.md +192 -0
  22. package/cursor/skills/mars-add-role/SKILL.md +156 -0
  23. package/cursor/skills/mars-add-server-action/SKILL.md +167 -0
  24. package/cursor/skills/mars-add-webhook/SKILL.md +192 -0
  25. package/cursor/skills/mars-build-complete-feature/SKILL.md +228 -0
  26. package/cursor/skills/mars-build-dashboard/SKILL.md +211 -0
  27. package/cursor/skills/mars-build-data-table/SKILL.md +284 -0
  28. package/cursor/skills/mars-build-form/SKILL.md +229 -0
  29. package/cursor/skills/mars-build-landing-page/SKILL.md +248 -0
  30. package/cursor/skills/mars-capture-conversation-context/SKILL.md +119 -0
  31. package/cursor/skills/mars-configure-ai/SKILL.md +617 -0
  32. package/cursor/skills/mars-configure-analytics/SKILL.md +413 -0
  33. package/cursor/skills/mars-configure-dark-mode/SKILL.md +309 -0
  34. package/cursor/skills/mars-configure-email/SKILL.md +170 -0
  35. package/cursor/skills/mars-configure-email-verification/SKILL.md +333 -0
  36. package/cursor/skills/mars-configure-feature-flags/SKILL.md +361 -0
  37. package/cursor/skills/mars-configure-i18n/SKILL.md +518 -0
  38. package/cursor/skills/mars-configure-jobs/SKILL.md +500 -0
  39. package/cursor/skills/mars-configure-magic-links/SKILL.md +385 -0
  40. package/cursor/skills/mars-configure-multi-tenancy/SKILL.md +611 -0
  41. package/cursor/skills/mars-configure-notifications/SKILL.md +569 -0
  42. package/cursor/skills/mars-configure-oauth/SKILL.md +217 -0
  43. package/cursor/skills/mars-configure-onboarding/SKILL.md +483 -0
  44. package/cursor/skills/mars-configure-payments/SKILL.md +243 -0
  45. package/cursor/skills/mars-configure-realtime/SKILL.md +733 -0
  46. package/cursor/skills/mars-configure-search/SKILL.md +581 -0
  47. package/cursor/skills/mars-configure-storage/SKILL.md +273 -0
  48. package/cursor/skills/mars-configure-two-factor/SKILL.md +518 -0
  49. package/cursor/skills/mars-create-execution-plan/SKILL.md +204 -0
  50. package/cursor/skills/mars-create-seed/SKILL.md +191 -0
  51. package/cursor/skills/mars-deploy-to-vercel/SKILL.md +300 -0
  52. package/cursor/skills/mars-design-tokens/SKILL.md +138 -0
  53. package/cursor/skills/mars-setup-billing/SKILL.md +322 -0
  54. package/cursor/skills/mars-setup-project/SKILL.md +104 -0
  55. package/cursor/skills/mars-setup-teams/SKILL.md +688 -0
  56. package/cursor/skills/mars-test-api-route/SKILL.md +219 -0
  57. package/cursor/skills/mars-update-architecture-docs/SKILL.md +189 -0
  58. package/dist/api-error/index.d.ts +27 -0
  59. package/dist/api-error/index.d.ts.map +1 -0
  60. package/dist/api-error/index.js +2 -0
  61. package/dist/auth/credential-tag.d.ts +5 -0
  62. package/dist/auth/credential-tag.d.ts.map +1 -0
  63. package/dist/auth/credential-tag.js +2 -0
  64. package/dist/auth/crypto-utils.d.ts +43 -0
  65. package/dist/auth/crypto-utils.d.ts.map +1 -0
  66. package/dist/auth/crypto-utils.js +1 -0
  67. package/dist/auth/csrf.d.ts +32 -0
  68. package/dist/auth/csrf.d.ts.map +1 -0
  69. package/dist/auth/csrf.js +2 -0
  70. package/dist/auth/hooks/index.d.ts +4 -0
  71. package/dist/auth/hooks/index.d.ts.map +1 -0
  72. package/dist/auth/hooks/index.js +68 -0
  73. package/dist/auth/hooks/useCSRF.d.ts +7 -0
  74. package/dist/auth/hooks/useCSRF.d.ts.map +1 -0
  75. package/dist/auth/hooks/usePasswordStrength.d.ts +17 -0
  76. package/dist/auth/hooks/usePasswordStrength.d.ts.map +1 -0
  77. package/dist/auth/internal-api-key.d.ts +5 -0
  78. package/dist/auth/internal-api-key.d.ts.map +1 -0
  79. package/dist/auth/internal-api-key.js +30 -0
  80. package/dist/auth/link-utils.d.ts +13 -0
  81. package/dist/auth/link-utils.d.ts.map +1 -0
  82. package/dist/auth/link-utils.js +1 -0
  83. package/dist/auth/middleware.d.ts +56 -0
  84. package/dist/auth/middleware.d.ts.map +1 -0
  85. package/dist/auth/middleware.js +3 -0
  86. package/dist/auth/password.d.ts +28 -0
  87. package/dist/auth/password.d.ts.map +1 -0
  88. package/dist/auth/password.js +1 -0
  89. package/dist/auth/reset-token.d.ts +3 -0
  90. package/dist/auth/reset-token.d.ts.map +1 -0
  91. package/dist/auth/reset-token.js +9 -0
  92. package/dist/auth/responses.d.ts +15 -0
  93. package/dist/auth/responses.d.ts.map +1 -0
  94. package/dist/auth/responses.js +2 -0
  95. package/dist/auth/session.d.ts +79 -0
  96. package/dist/auth/session.d.ts.map +1 -0
  97. package/dist/auth/session.js +1 -0
  98. package/dist/auth/types.d.ts +18 -0
  99. package/dist/auth/types.d.ts.map +1 -0
  100. package/dist/auth/types.js +10 -0
  101. package/dist/auth/validation.d.ts +146 -0
  102. package/dist/auth/validation.d.ts.map +1 -0
  103. package/dist/auth/validation.js +116 -0
  104. package/dist/auth/validators.d.ts +4 -0
  105. package/dist/auth/validators.d.ts.map +1 -0
  106. package/dist/auth/validators.js +27 -0
  107. package/dist/auth/verification.d.ts +54 -0
  108. package/dist/auth/verification.d.ts.map +1 -0
  109. package/dist/auth/verification.js +39 -0
  110. package/dist/chunk-4LS3QDD5.js +162 -0
  111. package/dist/chunk-ABBUHT5Z.js +110 -0
  112. package/dist/chunk-CTYAVMOF.js +15 -0
  113. package/dist/chunk-GVLH2GQP.js +14 -0
  114. package/dist/chunk-HOSMMQMA.js +109 -0
  115. package/dist/chunk-MXQ66RUN.js +28 -0
  116. package/dist/chunk-PZE3JGXO.js +149 -0
  117. package/dist/chunk-QAH2Y5WK.js +93 -0
  118. package/dist/chunk-QWMN5UJC.js +76 -0
  119. package/dist/chunk-ROQV54MU.js +117 -0
  120. package/dist/chunk-U4NZQ366.js +46 -0
  121. package/dist/chunk-WBJOIENS.js +22 -0
  122. package/dist/chunk-WO6FHJHG.js +29 -0
  123. package/dist/chunk-Z5BEKPJI.js +96 -0
  124. package/dist/chunk-ZA46T6GX.js +24 -0
  125. package/dist/configure-mars.d.ts +104 -0
  126. package/dist/configure-mars.d.ts.map +1 -0
  127. package/dist/database/index.d.ts +8 -0
  128. package/dist/database/index.d.ts.map +1 -0
  129. package/dist/database/index.js +1 -0
  130. package/dist/email/index.d.ts +25 -0
  131. package/dist/email/index.d.ts.map +1 -0
  132. package/dist/email/index.js +2 -0
  133. package/dist/email/types.d.ts +18 -0
  134. package/dist/email/types.d.ts.map +1 -0
  135. package/dist/env/index.d.ts +36 -0
  136. package/dist/env/index.d.ts.map +1 -0
  137. package/dist/env/index.js +1 -0
  138. package/dist/index.d.ts +6 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +163 -0
  141. package/dist/logger/index.d.ts +80 -0
  142. package/dist/logger/index.d.ts.map +1 -0
  143. package/dist/logger/index.js +1 -0
  144. package/dist/payments/index.d.ts +53 -0
  145. package/dist/payments/index.d.ts.map +1 -0
  146. package/dist/payments/index.js +72 -0
  147. package/dist/plugin/builtin/email-plugins.d.ts +10 -0
  148. package/dist/plugin/builtin/email-plugins.d.ts.map +1 -0
  149. package/dist/plugin/builtin/index.d.ts +4 -0
  150. package/dist/plugin/builtin/index.d.ts.map +1 -0
  151. package/dist/plugin/builtin/index.js +324 -0
  152. package/dist/plugin/builtin/payment-plugins.d.ts +4 -0
  153. package/dist/plugin/builtin/payment-plugins.d.ts.map +1 -0
  154. package/dist/plugin/builtin/storage-plugins.d.ts +5 -0
  155. package/dist/plugin/builtin/storage-plugins.d.ts.map +1 -0
  156. package/dist/plugin/index.d.ts +21 -0
  157. package/dist/plugin/index.d.ts.map +1 -0
  158. package/dist/plugin/index.js +30 -0
  159. package/dist/rate-limit/index.d.ts +89 -0
  160. package/dist/rate-limit/index.d.ts.map +1 -0
  161. package/dist/rate-limit/index.js +166 -0
  162. package/dist/seo/faq.d.ts +37 -0
  163. package/dist/seo/faq.d.ts.map +1 -0
  164. package/dist/seo/index.d.ts +75 -0
  165. package/dist/seo/index.d.ts.map +1 -0
  166. package/dist/seo/index.js +1 -0
  167. package/dist/storage/index.d.ts +50 -0
  168. package/dist/storage/index.d.ts.map +1 -0
  169. package/dist/storage/index.js +211 -0
  170. package/dist/test-utils/factories.d.ts +38 -0
  171. package/dist/test-utils/factories.d.ts.map +1 -0
  172. package/dist/test-utils/index.d.ts +6 -0
  173. package/dist/test-utils/index.d.ts.map +1 -0
  174. package/dist/test-utils/index.js +117 -0
  175. package/dist/test-utils/mock-auth.d.ts +25 -0
  176. package/dist/test-utils/mock-auth.d.ts.map +1 -0
  177. package/dist/test-utils/mock-prisma.d.ts +55 -0
  178. package/dist/test-utils/mock-prisma.d.ts.map +1 -0
  179. package/dist/test-utils/render.d.ts +4 -0
  180. package/dist/test-utils/render.d.ts.map +1 -0
  181. package/dist/test-utils/request-helpers.d.ts +6 -0
  182. package/dist/test-utils/request-helpers.d.ts.map +1 -0
  183. package/dist/types.d.ts +53 -0
  184. package/dist/types.d.ts.map +1 -0
  185. package/dist/utils/math.d.ts +2 -0
  186. package/dist/utils/math.d.ts.map +1 -0
  187. package/dist/utils/math.js +7 -0
  188. package/dist/utils/optional-import.d.ts +14 -0
  189. package/dist/utils/optional-import.d.ts.map +1 -0
  190. package/package.json +205 -0
  191. package/scripts/generate-skill-adapters.ts +146 -0
  192. package/scripts/postinstall.mjs +146 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-helpers.d.ts","sourceRoot":"","sources":["../../src/test-utils/request-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,KAAK,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE9D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAQ/E;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,WAAW,CASb"}
@@ -0,0 +1,53 @@
1
+ export interface MarsAppConfig {
2
+ name: string;
3
+ description: string;
4
+ url: string;
5
+ support: {
6
+ email: string;
7
+ };
8
+ features: {
9
+ auth: boolean;
10
+ admin: boolean;
11
+ darkMode: boolean;
12
+ [key: string]: boolean;
13
+ };
14
+ services: {
15
+ email: {
16
+ provider: string;
17
+ };
18
+ payments?: {
19
+ provider: string;
20
+ };
21
+ storage?: {
22
+ provider: string;
23
+ };
24
+ [key: string]: {
25
+ provider: string;
26
+ } | undefined;
27
+ };
28
+ }
29
+ export interface PrismaLike {
30
+ user: {
31
+ findUnique: (args: {
32
+ where: {
33
+ id: string;
34
+ };
35
+ select: Record<string, boolean>;
36
+ }) => Promise<Record<string, unknown> | null>;
37
+ };
38
+ }
39
+ export interface MarsServices {
40
+ email: {
41
+ provider: string;
42
+ };
43
+ storage?: {
44
+ provider: string;
45
+ };
46
+ payments?: {
47
+ provider: string;
48
+ };
49
+ [key: string]: {
50
+ provider: string;
51
+ } | undefined;
52
+ }
53
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,QAAQ,EAAE;QACR,IAAI,EAAE,OAAO,CAAC;QACd,KAAK,EAAE,OAAO,CAAC;QACf,QAAQ,EAAE,OAAO,CAAC;QAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,QAAQ,EAAE;QACR,KAAK,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5B,QAAQ,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC;QAChC,OAAO,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/B,CAAC,GAAG,EAAE,MAAM,GAAG;YAAE,QAAQ,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACjD,CAAC;CACH;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE;QACJ,UAAU,EAAE,CAAC,IAAI,EAAE;YACjB,KAAK,EAAE;gBAAE,EAAE,EAAE,MAAM,CAAA;aAAE,CAAC;YACtB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SACjC,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;KAC/C,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;CACjD"}
@@ -0,0 +1,2 @@
1
+ export declare function calculatePercentage(x: number, y: number): number;
2
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/utils/math.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGhE"}
@@ -0,0 +1,7 @@
1
+ // src/utils/math.ts
2
+ function calculatePercentage(x, y) {
3
+ if (y === 0) return 0;
4
+ return x / y * 100;
5
+ }
6
+
7
+ export { calculatePercentage };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Dynamically imports an optional peer dependency at runtime.
3
+ *
4
+ * Uses a function parameter as the specifier so that bundlers (webpack,
5
+ * Turbopack, esbuild) cannot statically resolve the module at compile
6
+ * time. This prevents "Module not found" errors when an optional peer
7
+ * dep is not installed in the consuming project.
8
+ *
9
+ * The import only executes when the code path is actually reached at
10
+ * runtime — e.g. only the Resend SDK is imported when the Resend
11
+ * email provider is configured, never when SendGrid is active.
12
+ */
13
+ export declare function importOptional<T = unknown>(specifier: string): Promise<T>;
14
+ //# sourceMappingURL=optional-import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional-import.d.ts","sourceRoot":"","sources":["../../src/utils/optional-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAS/E"}
package/package.json ADDED
@@ -0,0 +1,205 @@
1
+ {
2
+ "name": "@mars-stack/core",
3
+ "version": "0.4.0",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/greaveselliott/mars.git"
8
+ },
9
+ "homepage": "https://github.com/greaveselliott/mars#readme",
10
+ "keywords": [
11
+ "saas",
12
+ "nextjs",
13
+ "prisma",
14
+ "auth",
15
+ "fullstack"
16
+ ],
17
+ "type": "module",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ },
23
+ "./database": {
24
+ "types": "./dist/database/index.d.ts",
25
+ "import": "./dist/database/index.js"
26
+ },
27
+ "./rate-limit": {
28
+ "types": "./dist/rate-limit/index.d.ts",
29
+ "import": "./dist/rate-limit/index.js"
30
+ },
31
+ "./auth/password": {
32
+ "types": "./dist/auth/password.d.ts",
33
+ "import": "./dist/auth/password.js"
34
+ },
35
+ "./auth/verification": {
36
+ "types": "./dist/auth/verification.d.ts",
37
+ "import": "./dist/auth/verification.js"
38
+ },
39
+ "./auth/validation": {
40
+ "types": "./dist/auth/validation.d.ts",
41
+ "import": "./dist/auth/validation.js"
42
+ },
43
+ "./auth/responses": {
44
+ "types": "./dist/auth/responses.d.ts",
45
+ "import": "./dist/auth/responses.js"
46
+ },
47
+ "./auth/link-utils": {
48
+ "types": "./dist/auth/link-utils.d.ts",
49
+ "import": "./dist/auth/link-utils.js"
50
+ },
51
+ "./auth/hooks": {
52
+ "types": "./dist/auth/hooks/index.d.ts",
53
+ "import": "./dist/auth/hooks/index.js"
54
+ },
55
+ "./auth/credential-tag": {
56
+ "types": "./dist/auth/credential-tag.d.ts",
57
+ "import": "./dist/auth/credential-tag.js"
58
+ },
59
+ "./auth/reset-token": {
60
+ "types": "./dist/auth/reset-token.d.ts",
61
+ "import": "./dist/auth/reset-token.js"
62
+ },
63
+ "./auth/internal-api-key": {
64
+ "types": "./dist/auth/internal-api-key.d.ts",
65
+ "import": "./dist/auth/internal-api-key.js"
66
+ },
67
+ "./auth/crypto-utils": {
68
+ "types": "./dist/auth/crypto-utils.d.ts",
69
+ "import": "./dist/auth/crypto-utils.js"
70
+ },
71
+ "./auth/csrf": {
72
+ "types": "./dist/auth/csrf.d.ts",
73
+ "import": "./dist/auth/csrf.js"
74
+ },
75
+ "./auth/middleware": {
76
+ "types": "./dist/auth/middleware.d.ts",
77
+ "import": "./dist/auth/middleware.js"
78
+ },
79
+ "./auth/session": {
80
+ "types": "./dist/auth/session.d.ts",
81
+ "import": "./dist/auth/session.js"
82
+ },
83
+ "./auth/types": {
84
+ "types": "./dist/auth/types.d.ts",
85
+ "import": "./dist/auth/types.js"
86
+ },
87
+ "./auth/validators": {
88
+ "types": "./dist/auth/validators.d.ts",
89
+ "import": "./dist/auth/validators.js"
90
+ },
91
+ "./seo": {
92
+ "types": "./dist/seo/index.d.ts",
93
+ "import": "./dist/seo/index.js"
94
+ },
95
+ "./utils/math": {
96
+ "types": "./dist/utils/math.d.ts",
97
+ "import": "./dist/utils/math.js"
98
+ },
99
+ "./payments": {
100
+ "types": "./dist/payments/index.d.ts",
101
+ "import": "./dist/payments/index.js"
102
+ },
103
+ "./storage": {
104
+ "types": "./dist/storage/index.d.ts",
105
+ "import": "./dist/storage/index.js"
106
+ },
107
+ "./plugin": {
108
+ "types": "./dist/plugin/index.d.ts",
109
+ "import": "./dist/plugin/index.js"
110
+ },
111
+ "./plugin/builtin": {
112
+ "types": "./dist/plugin/builtin/index.d.ts",
113
+ "import": "./dist/plugin/builtin/index.js"
114
+ },
115
+ "./test-utils": {
116
+ "types": "./dist/test-utils/index.d.ts",
117
+ "import": "./dist/test-utils/index.js"
118
+ }
119
+ },
120
+ "publishConfig": {
121
+ "access": "restricted"
122
+ },
123
+ "files": [
124
+ "dist",
125
+ "cursor",
126
+ "scripts"
127
+ ],
128
+ "scripts": {
129
+ "build": "tsup && tsc -p tsconfig.build.json",
130
+ "dev": "tsup --watch",
131
+ "postinstall": "node scripts/postinstall.mjs",
132
+ "test": "vitest run",
133
+ "test:watch": "vitest",
134
+ "test:coverage": "vitest run --coverage",
135
+ "prepublishOnly": "yarn build"
136
+ },
137
+ "sideEffects": false,
138
+ "peerDependencies": {
139
+ "@aws-sdk/client-s3": ">=3.0.0",
140
+ "@aws-sdk/s3-request-presigner": ">=3.0.0",
141
+ "@prisma/client": ">=5",
142
+ "@sendgrid/mail": ">=7.0.0",
143
+ "@upstash/ratelimit": ">=2.0.0",
144
+ "@upstash/redis": ">=1.20.0",
145
+ "@vercel/blob": ">=0.20.0",
146
+ "next": ">=14",
147
+ "react": ">=18",
148
+ "resend": ">=1.0.0",
149
+ "stripe": ">=14.0.0"
150
+ },
151
+ "peerDependenciesMeta": {
152
+ "@prisma/client": {
153
+ "optional": true
154
+ },
155
+ "@sendgrid/mail": {
156
+ "optional": true
157
+ },
158
+ "@upstash/ratelimit": {
159
+ "optional": true
160
+ },
161
+ "@upstash/redis": {
162
+ "optional": true
163
+ },
164
+ "resend": {
165
+ "optional": true
166
+ },
167
+ "stripe": {
168
+ "optional": true
169
+ },
170
+ "@vercel/blob": {
171
+ "optional": true
172
+ },
173
+ "@aws-sdk/client-s3": {
174
+ "optional": true
175
+ },
176
+ "@aws-sdk/s3-request-presigner": {
177
+ "optional": true
178
+ }
179
+ },
180
+ "dependencies": {
181
+ "bcryptjs": "^2.4.3",
182
+ "jose": "^6.2.1",
183
+ "pino": "^9.6.0",
184
+ "zod": "^4.3.6"
185
+ },
186
+ "devDependencies": {
187
+ "@aws-sdk/client-s3": "^3.1007.0",
188
+ "@aws-sdk/s3-request-presigner": "^3.1007.0",
189
+ "@testing-library/react": "^16.0.0",
190
+ "@types/bcryptjs": "^2.4.0",
191
+ "@types/fs-extra": "^11.0.4",
192
+ "@types/react": "^19.0.0",
193
+ "@upstash/ratelimit": "^2.0.0",
194
+ "@upstash/redis": "^1.36.4",
195
+ "@vercel/blob": "^2.3.1",
196
+ "fs-extra": "^11.3.4",
197
+ "next": "^16.0.0",
198
+ "react": "^19.0.0",
199
+ "resend": "^6.9.3",
200
+ "stripe": "^17.0.0",
201
+ "tsup": "^8.0.0",
202
+ "typescript": "^5.7.0",
203
+ "vitest": "^3.0.0"
204
+ }
205
+ }
@@ -0,0 +1,146 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+
4
+ interface SkillManifestEntry {
5
+ file: string;
6
+ triggers: string[];
7
+ dependencies?: string[];
8
+ capabilities?: string[];
9
+ }
10
+
11
+ interface Manifest {
12
+ skills: Record<string, SkillManifestEntry>;
13
+ }
14
+
15
+ const CORE_DIR = path.resolve(__dirname, '..');
16
+ const SKILLS_DIR = path.join(CORE_DIR, 'cursor/skills');
17
+ const MANIFEST_PATH = path.join(CORE_DIR, 'cursor/manifest.json');
18
+
19
+ async function generateCursorOutput(
20
+ outputDir: string,
21
+ manifest: Manifest,
22
+ ): Promise<void> {
23
+ const destDir = path.join(outputDir, '.cursor/skills');
24
+ await fs.ensureDir(destDir);
25
+
26
+ for (const [name] of Object.entries(manifest.skills)) {
27
+ const srcDir = path.join(SKILLS_DIR, `mars-${name}`);
28
+ const destSkillDir = path.join(destDir, `mars-${name}`);
29
+
30
+ if (await fs.pathExists(srcDir)) {
31
+ await fs.copy(srcDir, destSkillDir, { overwrite: true });
32
+ }
33
+ }
34
+ }
35
+
36
+ async function generateWindsurfOutput(
37
+ outputDir: string,
38
+ manifest: Manifest,
39
+ ): Promise<void> {
40
+ const rules: string[] = ['# Mars Project Rules\n'];
41
+
42
+ for (const [name, entry] of Object.entries(manifest.skills)) {
43
+ const skillPath = path.join(SKILLS_DIR, `mars-${name}`, 'SKILL.md');
44
+ if (await fs.pathExists(skillPath)) {
45
+ const content = await fs.readFile(skillPath, 'utf-8');
46
+ rules.push(`\n## Skill: ${name}\n`);
47
+ rules.push(`Triggers: ${entry.triggers.join(', ')}\n`);
48
+ rules.push(content);
49
+ }
50
+ }
51
+
52
+ await fs.writeFile(path.join(outputDir, '.windsurfrules'), rules.join('\n'));
53
+ }
54
+
55
+ async function generateCopilotOutput(
56
+ outputDir: string,
57
+ manifest: Manifest,
58
+ ): Promise<void> {
59
+ const lines: string[] = [
60
+ '# Mars Project Instructions for GitHub Copilot\n',
61
+ '## Architecture\n',
62
+ ];
63
+
64
+ const agentsPath = path.join(outputDir, 'AGENTS.md');
65
+ if (await fs.pathExists(agentsPath)) {
66
+ const agentsContent = await fs.readFile(agentsPath, 'utf-8');
67
+ lines.push(agentsContent);
68
+ }
69
+
70
+ lines.push('\n## Available Skills\n');
71
+ for (const [name, entry] of Object.entries(manifest.skills)) {
72
+ lines.push(`- **${name}**: Triggers: ${entry.triggers.join(', ')}`);
73
+ if (entry.dependencies?.length) {
74
+ lines.push(` Dependencies: ${entry.dependencies.join(', ')}`);
75
+ }
76
+ }
77
+
78
+ await fs.ensureDir(path.join(outputDir, '.github'));
79
+ await fs.writeFile(
80
+ path.join(outputDir, '.github/copilot-instructions.md'),
81
+ lines.join('\n'),
82
+ );
83
+ }
84
+
85
+ async function generateCodexOutput(
86
+ outputDir: string,
87
+ manifest: Manifest,
88
+ ): Promise<void> {
89
+ const skillsDir = path.join(outputDir, 'docs/skills');
90
+ await fs.ensureDir(skillsDir);
91
+
92
+ for (const [name] of Object.entries(manifest.skills)) {
93
+ const skillPath = path.join(SKILLS_DIR, `mars-${name}`, 'SKILL.md');
94
+ if (await fs.pathExists(skillPath)) {
95
+ await fs.copy(skillPath, path.join(skillsDir, `${name}.md`));
96
+ }
97
+ }
98
+
99
+ const index: string[] = ['# Available Skills\n'];
100
+ for (const [name, entry] of Object.entries(manifest.skills)) {
101
+ index.push(`## ${name}\n`);
102
+ index.push(`- **Triggers**: ${entry.triggers.join(', ')}`);
103
+ if (entry.dependencies?.length) {
104
+ index.push(`- **Dependencies**: ${entry.dependencies.join(', ')}`);
105
+ }
106
+ index.push(`- **File**: [${name}.md](./skills/${name}.md)\n`);
107
+ }
108
+ await fs.writeFile(
109
+ path.join(outputDir, 'docs/skill-index.md'),
110
+ index.join('\n'),
111
+ );
112
+ }
113
+
114
+ type GeneratorFn = (dir: string, m: Manifest) => Promise<void>;
115
+
116
+ const GENERATORS: Record<string, GeneratorFn> = {
117
+ cursor: generateCursorOutput,
118
+ windsurf: generateWindsurfOutput,
119
+ copilot: generateCopilotOutput,
120
+ codex: generateCodexOutput,
121
+ };
122
+
123
+ export const SUPPORTED_TARGETS = Object.keys(GENERATORS);
124
+
125
+ async function main(): Promise<void> {
126
+ const manifest: Manifest = await fs.readJson(MANIFEST_PATH);
127
+ const outputDir = process.argv[2] || '.';
128
+ const target = process.argv[3] || 'all';
129
+
130
+ if (target === 'all') {
131
+ for (const gen of Object.values(GENERATORS)) {
132
+ await gen(outputDir, manifest);
133
+ }
134
+ } else if (GENERATORS[target]) {
135
+ await GENERATORS[target](outputDir, manifest);
136
+ } else {
137
+ console.error(
138
+ `Unknown target: ${target}. Available: ${SUPPORTED_TARGETS.join(', ')}`,
139
+ );
140
+ process.exit(1);
141
+ }
142
+
143
+ console.log(`Generated skill adapters for: ${target}`);
144
+ }
145
+
146
+ main().catch(console.error);
@@ -0,0 +1,146 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+
4
+ const packageDir = path.dirname(new URL(import.meta.url).pathname);
5
+ const projectRoot = process.env.INIT_CWD || process.cwd();
6
+ const pkgJsonPath = path.join(projectRoot, 'package.json');
7
+
8
+ if (!fs.existsSync(pkgJsonPath)) process.exit(0);
9
+
10
+ let pkgJson;
11
+ try {
12
+ pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
13
+ } catch {
14
+ process.exit(0);
15
+ }
16
+
17
+ const isMarsProject = pkgJson.mars !== undefined
18
+ || pkgJson.dependencies?.['@mars-stack/core'] !== undefined;
19
+
20
+ if (!isMarsProject) process.exit(0);
21
+
22
+ /**
23
+ * Detect which IDE environment the project is running in.
24
+ * Falls back to 'cursor' as the default since that's the primary target.
25
+ */
26
+ function detectIdeEnvironment() {
27
+ if (fs.existsSync(path.join(projectRoot, '.windsurf')) ||
28
+ process.env.WINDSURF_WORKSPACE) {
29
+ return 'windsurf';
30
+ }
31
+
32
+ if (fs.existsSync(path.join(projectRoot, '.github', 'copilot-instructions.md')) ||
33
+ process.env.GITHUB_COPILOT) {
34
+ return 'copilot';
35
+ }
36
+
37
+ if (fs.existsSync(path.join(projectRoot, '.codex')) ||
38
+ process.env.CODEX_HOME) {
39
+ return 'codex';
40
+ }
41
+
42
+ return 'cursor';
43
+ }
44
+
45
+ const ide = detectIdeEnvironment();
46
+
47
+ // Cursor: copy rules + skills into .cursor/ (primary target)
48
+ const copies = [
49
+ { src: 'rules', dest: '.cursor/rules' },
50
+ { src: 'skills', dest: '.cursor/skills' },
51
+ ];
52
+
53
+ for (const { src, dest } of copies) {
54
+ const srcDir = path.join(packageDir, '..', 'cursor', src);
55
+ const destDir = path.join(projectRoot, dest);
56
+ if (!fs.existsSync(srcDir)) continue;
57
+
58
+ fs.mkdirSync(destDir, { recursive: true });
59
+
60
+ const entries = fs.readdirSync(srcDir, { withFileTypes: true });
61
+ for (const entry of entries) {
62
+ if (entry.isFile() && entry.name.startsWith('mars-')) {
63
+ fs.copyFileSync(
64
+ path.join(srcDir, entry.name),
65
+ path.join(destDir, entry.name),
66
+ );
67
+ } else if (entry.isDirectory() && entry.name.startsWith('mars-')) {
68
+ fs.cpSync(
69
+ path.join(srcDir, entry.name),
70
+ path.join(destDir, entry.name),
71
+ { recursive: true },
72
+ );
73
+ }
74
+ }
75
+ }
76
+
77
+ // Generate IDE-specific adapter files for non-Cursor environments
78
+ if (ide !== 'cursor') {
79
+ const manifestPath = path.join(packageDir, '..', 'cursor', 'manifest.json');
80
+ if (!fs.existsSync(manifestPath)) process.exit(0);
81
+
82
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
83
+ const skillsDir = path.join(packageDir, '..', 'cursor', 'skills');
84
+
85
+ if (ide === 'windsurf') {
86
+ const rules = ['# Mars Project Rules\n'];
87
+
88
+ for (const [name, entry] of Object.entries(manifest.skills)) {
89
+ const skillPath = path.join(skillsDir, `mars-${name}`, 'SKILL.md');
90
+ if (fs.existsSync(skillPath)) {
91
+ const content = fs.readFileSync(skillPath, 'utf-8');
92
+ rules.push(`\n## Skill: ${name}\n`);
93
+ rules.push(`Triggers: ${/** @type {{ triggers: string[] }} */ (entry).triggers.join(', ')}\n`);
94
+ rules.push(content);
95
+ }
96
+ }
97
+
98
+ fs.writeFileSync(path.join(projectRoot, '.windsurfrules'), rules.join('\n'));
99
+ }
100
+
101
+ if (ide === 'copilot') {
102
+ const lines = ['# Mars Project Instructions for GitHub Copilot\n'];
103
+
104
+ const agentsPath = path.join(projectRoot, 'AGENTS.md');
105
+ if (fs.existsSync(agentsPath)) {
106
+ lines.push(fs.readFileSync(agentsPath, 'utf-8'));
107
+ }
108
+
109
+ lines.push('\n## Available Skills\n');
110
+ for (const [name, entry] of Object.entries(manifest.skills)) {
111
+ const typedEntry = /** @type {{ triggers: string[]; dependencies?: string[] }} */ (entry);
112
+ lines.push(`- **${name}**: Triggers: ${typedEntry.triggers.join(', ')}`);
113
+ if (typedEntry.dependencies?.length) {
114
+ lines.push(` Dependencies: ${typedEntry.dependencies.join(', ')}`);
115
+ }
116
+ }
117
+
118
+ const ghDir = path.join(projectRoot, '.github');
119
+ fs.mkdirSync(ghDir, { recursive: true });
120
+ fs.writeFileSync(path.join(ghDir, 'copilot-instructions.md'), lines.join('\n'));
121
+ }
122
+
123
+ if (ide === 'codex') {
124
+ const docsSkillsDir = path.join(projectRoot, 'docs', 'skills');
125
+ fs.mkdirSync(docsSkillsDir, { recursive: true });
126
+
127
+ for (const [name] of Object.entries(manifest.skills)) {
128
+ const skillPath = path.join(skillsDir, `mars-${name}`, 'SKILL.md');
129
+ if (fs.existsSync(skillPath)) {
130
+ fs.copyFileSync(skillPath, path.join(docsSkillsDir, `${name}.md`));
131
+ }
132
+ }
133
+
134
+ const index = ['# Available Skills\n'];
135
+ for (const [name, entry] of Object.entries(manifest.skills)) {
136
+ const typedEntry = /** @type {{ triggers: string[]; dependencies?: string[] }} */ (entry);
137
+ index.push(`## ${name}\n`);
138
+ index.push(`- **Triggers**: ${typedEntry.triggers.join(', ')}`);
139
+ if (typedEntry.dependencies?.length) {
140
+ index.push(`- **Dependencies**: ${typedEntry.dependencies.join(', ')}`);
141
+ }
142
+ index.push(`- **File**: [${name}.md](./skills/${name}.md)\n`);
143
+ }
144
+ fs.writeFileSync(path.join(projectRoot, 'docs', 'skill-index.md'), index.join('\n'));
145
+ }
146
+ }