@leanspec/ui 0.2.3 → 0.2.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.
Files changed (187) hide show
  1. package/dist/standalone/packages/web/.next/BUILD_ID +1 -1
  2. package/dist/standalone/packages/web/.next/build-manifest.json +2 -2
  3. package/dist/standalone/packages/web/.next/prerender-manifest.json +3 -3
  4. package/dist/standalone/packages/web/.next/server/app/_global-error.html +2 -2
  5. package/dist/standalone/packages/web/.next/server/app/_global-error.rsc +1 -1
  6. package/dist/standalone/packages/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/dist/standalone/packages/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/dist/standalone/packages/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  9. package/dist/standalone/packages/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/dist/standalone/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  11. package/dist/standalone/packages/web/.next/server/app/_not-found.html +2 -2
  12. package/dist/standalone/packages/web/.next/server/app/_not-found.rsc +2 -2
  13. package/dist/standalone/packages/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  14. package/dist/standalone/packages/web/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  15. package/dist/standalone/packages/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  16. package/dist/standalone/packages/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  17. package/dist/standalone/packages/web/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  18. package/dist/standalone/packages/web/.next/server/app/api/projects/[id]/specs/route.js.nft.json +1 -1
  19. package/dist/standalone/packages/web/.next/server/app/api/projects/route.js.nft.json +1 -1
  20. package/dist/standalone/packages/web/.next/server/app/api/revalidate/route.js.nft.json +1 -1
  21. package/dist/standalone/packages/web/.next/server/app/api/specs/[id]/dependency-graph/route.js.nft.json +1 -1
  22. package/dist/standalone/packages/web/.next/server/app/api/specs/[id]/route.js.nft.json +1 -1
  23. package/dist/standalone/packages/web/.next/server/app/api/specs/[id]/subspecs/[file]/route.js.nft.json +1 -1
  24. package/dist/standalone/packages/web/.next/server/app/api/stats/route.js.nft.json +1 -1
  25. package/dist/standalone/packages/web/.next/server/app/board/page.js.nft.json +1 -1
  26. package/dist/standalone/packages/web/.next/server/app/board.html +1 -1
  27. package/dist/standalone/packages/web/.next/server/app/board.rsc +2 -2
  28. package/dist/standalone/packages/web/.next/server/app/board.segments/_full.segment.rsc +2 -2
  29. package/dist/standalone/packages/web/.next/server/app/board.segments/_index.segment.rsc +1 -1
  30. package/dist/standalone/packages/web/.next/server/app/board.segments/_tree.segment.rsc +1 -1
  31. package/dist/standalone/packages/web/.next/server/app/board.segments/board/__PAGE__.segment.rsc +1 -1
  32. package/dist/standalone/packages/web/.next/server/app/board.segments/board.segment.rsc +1 -1
  33. package/dist/standalone/packages/web/.next/server/app/page.js.nft.json +1 -1
  34. package/dist/standalone/packages/web/.next/server/app/specs/[id]/page.js.nft.json +1 -1
  35. package/dist/standalone/packages/web/.next/server/app/specs/[id]/page_client-reference-manifest.js +1 -1
  36. package/dist/standalone/packages/web/.next/server/app/specs/page.js.nft.json +1 -1
  37. package/dist/standalone/packages/web/.next/server/app/stats/page.js.nft.json +1 -1
  38. package/dist/standalone/packages/web/.next/server/chunks/[root-of-the-server]__2e0f9179._.js +1 -1
  39. package/dist/standalone/packages/web/.next/server/chunks/[root-of-the-server]__577d6d08._.js +1 -1
  40. package/dist/standalone/packages/web/.next/server/chunks/[root-of-the-server]__e54bc4b8._.js +1 -1
  41. package/dist/standalone/packages/web/.next/server/chunks/[root-of-the-server]__f8978f3e._.js +1 -1
  42. package/dist/standalone/packages/web/.next/server/chunks/ssr/[root-of-the-server]__be46bb7c._.js +1 -1
  43. package/dist/standalone/packages/web/.next/server/chunks/ssr/_7dedc302._.js +1 -1
  44. package/dist/standalone/packages/web/.next/server/chunks/ssr/_ad71cd8c._.js +1 -1
  45. package/dist/standalone/packages/web/.next/server/chunks/ssr/_c5a5c652._.js +1 -1
  46. package/dist/standalone/packages/web/.next/server/pages/404.html +2 -2
  47. package/dist/standalone/packages/web/.next/server/pages/500.html +2 -2
  48. package/dist/standalone/packages/web/.next/server/server-reference-manifest.js +1 -1
  49. package/dist/standalone/packages/web/.next/server/server-reference-manifest.json +1 -1
  50. package/dist/{static/chunks/0de258404bcae76f.js → standalone/packages/web/.next/static/chunks/8864b47e107cbe63.js} +1 -1
  51. package/dist/{static/chunks/09ff02250dd56621.js → standalone/packages/web/.next/static/chunks/a2889ecda42c83e7.js} +1 -1
  52. package/dist/standalone/packages/web/.next/static/chunks/c22619397bb8368e.js +1 -0
  53. package/dist/standalone/packages/web/components.json +20 -0
  54. package/dist/standalone/packages/web/drizzle/0000_reflective_thena.sql +59 -0
  55. package/dist/standalone/packages/web/drizzle/0001_fresh_carmella_unuscione.sql +1 -0
  56. package/dist/standalone/packages/web/drizzle/meta/0000_snapshot.json +427 -0
  57. package/dist/standalone/packages/web/drizzle/meta/0001_snapshot.json +436 -0
  58. package/dist/standalone/packages/web/drizzle/meta/_journal.json +20 -0
  59. package/dist/standalone/packages/web/drizzle.config.ts +10 -0
  60. package/dist/standalone/packages/web/eslint.config.mjs +18 -0
  61. package/dist/standalone/packages/web/next.config.ts +7 -0
  62. package/dist/standalone/packages/web/package.json +1 -1
  63. package/dist/standalone/packages/web/postcss.config.mjs +8 -0
  64. package/dist/standalone/packages/web/src/app/api/projects/[id]/specs/route.ts +23 -0
  65. package/dist/standalone/packages/web/src/app/api/projects/route.ts +19 -0
  66. package/dist/standalone/packages/web/src/app/api/revalidate/route.ts +63 -0
  67. package/dist/standalone/packages/web/src/app/api/specs/[id]/dependency-graph/route.test.ts +51 -0
  68. package/dist/standalone/packages/web/src/app/api/specs/[id]/dependency-graph/route.ts +171 -0
  69. package/dist/standalone/packages/web/src/app/api/specs/[id]/route.ts +36 -0
  70. package/dist/standalone/packages/web/src/app/api/specs/[id]/subspecs/[file]/route.ts +46 -0
  71. package/dist/standalone/packages/web/src/app/api/stats/route.ts +19 -0
  72. package/dist/standalone/packages/web/src/app/board/board-client.tsx +162 -0
  73. package/dist/standalone/packages/web/src/app/board/loading.tsx +43 -0
  74. package/dist/standalone/packages/web/src/app/board/page.tsx +18 -0
  75. package/dist/standalone/packages/web/src/app/dashboard-client.tsx +364 -0
  76. package/dist/standalone/packages/web/src/app/error.tsx +43 -0
  77. package/dist/standalone/packages/web/src/app/globals.css +531 -0
  78. package/dist/standalone/packages/web/src/app/home-client.tsx +277 -0
  79. package/dist/standalone/packages/web/src/app/layout.tsx +70 -0
  80. package/dist/standalone/packages/web/src/app/loading.tsx +87 -0
  81. package/dist/standalone/packages/web/src/app/not-found.tsx +27 -0
  82. package/dist/standalone/packages/web/src/app/page.tsx +18 -0
  83. package/dist/standalone/packages/web/src/app/specs/[id]/loading.tsx +5 -0
  84. package/dist/standalone/packages/web/src/app/specs/[id]/page.tsx +43 -0
  85. package/dist/standalone/packages/web/src/app/specs/page.tsx +18 -0
  86. package/dist/standalone/packages/web/src/app/specs/specs-client.tsx +425 -0
  87. package/dist/standalone/packages/web/src/app/stats/page.tsx +18 -0
  88. package/dist/standalone/packages/web/src/app/stats/stats-client.tsx +283 -0
  89. package/dist/standalone/packages/web/src/components/back-to-top.tsx +46 -0
  90. package/dist/standalone/packages/web/src/components/empty-state.tsx +52 -0
  91. package/dist/standalone/packages/web/src/components/main-sidebar.tsx +175 -0
  92. package/dist/standalone/packages/web/src/components/markdown-link.test.ts +96 -0
  93. package/dist/standalone/packages/web/src/components/markdown-link.tsx +95 -0
  94. package/dist/standalone/packages/web/src/components/navigation.tsx +210 -0
  95. package/dist/standalone/packages/web/src/components/priority-badge.tsx +53 -0
  96. package/dist/standalone/packages/web/src/components/quick-search.tsx +180 -0
  97. package/dist/standalone/packages/web/src/components/skeletons.tsx +119 -0
  98. package/dist/standalone/packages/web/src/components/spec-dependency-graph.tsx +369 -0
  99. package/dist/standalone/packages/web/src/components/spec-detail-client.tsx +372 -0
  100. package/dist/standalone/packages/web/src/components/spec-detail-loading-shell.tsx +42 -0
  101. package/dist/standalone/packages/web/src/components/spec-detail-wrapper.tsx +70 -0
  102. package/dist/standalone/packages/web/src/components/spec-metadata.tsx +136 -0
  103. package/dist/standalone/packages/web/src/components/spec-sidebar.tsx +127 -0
  104. package/dist/standalone/packages/web/src/components/spec-timeline.tsx +186 -0
  105. package/dist/standalone/packages/web/src/components/specs-nav-sidebar.tsx +561 -0
  106. package/dist/standalone/packages/web/src/components/status-badge.tsx +53 -0
  107. package/dist/standalone/packages/web/src/components/sub-spec-tabs.tsx +143 -0
  108. package/dist/standalone/packages/web/src/components/table-of-contents.tsx +130 -0
  109. package/dist/standalone/packages/web/src/components/theme-provider.tsx +11 -0
  110. package/dist/standalone/packages/web/src/components/theme-toggle.tsx +37 -0
  111. package/dist/standalone/packages/web/src/components/ui/avatar.tsx +50 -0
  112. package/dist/standalone/packages/web/src/components/ui/badge.tsx +36 -0
  113. package/dist/standalone/packages/web/src/components/ui/breadcrumb.tsx +110 -0
  114. package/dist/standalone/packages/web/src/components/ui/button.tsx +57 -0
  115. package/dist/standalone/packages/web/src/components/ui/card.tsx +76 -0
  116. package/dist/standalone/packages/web/src/components/ui/command.tsx +153 -0
  117. package/dist/standalone/packages/web/src/components/ui/dialog.tsx +122 -0
  118. package/dist/standalone/packages/web/src/components/ui/input.tsx +24 -0
  119. package/dist/standalone/packages/web/src/components/ui/select.tsx +159 -0
  120. package/dist/standalone/packages/web/src/components/ui/separator.tsx +31 -0
  121. package/dist/standalone/packages/web/src/components/ui/skeleton.tsx +15 -0
  122. package/dist/standalone/packages/web/src/components/ui/tabs.tsx +55 -0
  123. package/dist/standalone/packages/web/src/components/ui/toast.tsx +30 -0
  124. package/dist/standalone/packages/web/src/components/ui/tooltip.tsx +32 -0
  125. package/dist/standalone/packages/web/src/lib/date-utils.ts +76 -0
  126. package/dist/standalone/packages/web/src/lib/db/index.ts +42 -0
  127. package/dist/standalone/packages/web/src/lib/db/migrate.ts +18 -0
  128. package/dist/standalone/packages/web/src/lib/db/queries.ts +114 -0
  129. package/dist/standalone/packages/web/src/lib/db/schema.ts +123 -0
  130. package/dist/standalone/packages/web/src/lib/db/seed.ts +156 -0
  131. package/dist/standalone/packages/web/src/lib/db/service-queries.ts +216 -0
  132. package/dist/standalone/packages/web/src/lib/dependency-graph.ts +105 -0
  133. package/dist/standalone/packages/web/src/lib/specs/service.ts +120 -0
  134. package/dist/standalone/packages/web/src/lib/specs/sources/database-source.ts +94 -0
  135. package/dist/standalone/packages/web/src/lib/specs/sources/filesystem-source.ts +249 -0
  136. package/dist/standalone/packages/web/src/lib/specs/types.ts +55 -0
  137. package/dist/standalone/packages/web/src/lib/stores/specs-sidebar-store.ts +152 -0
  138. package/dist/standalone/packages/web/src/lib/sub-specs.ts +171 -0
  139. package/dist/standalone/packages/web/src/lib/utils.ts +17 -0
  140. package/dist/standalone/packages/web/src/types/specs.ts +18 -0
  141. package/dist/standalone/packages/web/tailwind.config.ts +58 -0
  142. package/dist/standalone/packages/web/tsconfig.json +34 -0
  143. package/dist/standalone/packages/web/vitest.config.ts +14 -0
  144. package/dist/standalone/specs/100-release-process-typecheck-failure/README.md +266 -0
  145. package/dist/standalone/specs/101-sidebar-scroll-position-drift/README.md +100 -0
  146. package/package.json +5 -3
  147. package/dist/BUILD_ID +0 -1
  148. package/dist/static/chunks/a3e649fcddd3d715.js +0 -1
  149. /package/dist/{static/Z_BxkB0KJViCNbULN1S5p → standalone/packages/web/.next/static/DDHAmoL_2Poji-whvFjry}/_buildManifest.js +0 -0
  150. /package/dist/{static/Z_BxkB0KJViCNbULN1S5p → standalone/packages/web/.next/static/DDHAmoL_2Poji-whvFjry}/_clientMiddlewareManifest.json +0 -0
  151. /package/dist/{static/Z_BxkB0KJViCNbULN1S5p → standalone/packages/web/.next/static/DDHAmoL_2Poji-whvFjry}/_ssgManifest.js +0 -0
  152. /package/dist/{static → standalone/packages/web/.next/static}/chunks/0c19c69aa7625475.js +0 -0
  153. /package/dist/{static → standalone/packages/web/.next/static}/chunks/116800b03245a1e5.js +0 -0
  154. /package/dist/{static → standalone/packages/web/.next/static}/chunks/19e80edf527aef5c.js +0 -0
  155. /package/dist/{static → standalone/packages/web/.next/static}/chunks/2ece90370908f56c.js +0 -0
  156. /package/dist/{static → standalone/packages/web/.next/static}/chunks/36fd2dddb486f6bc.js +0 -0
  157. /package/dist/{static → standalone/packages/web/.next/static}/chunks/5c2072ad938de8ed.js +0 -0
  158. /package/dist/{static → standalone/packages/web/.next/static}/chunks/6577fe797a336bab.js +0 -0
  159. /package/dist/{static → standalone/packages/web/.next/static}/chunks/6a05a93ec8fa7b83.js +0 -0
  160. /package/dist/{static → standalone/packages/web/.next/static}/chunks/7f732ea69e643219.js +0 -0
  161. /package/dist/{static → standalone/packages/web/.next/static}/chunks/a02c1f50ff00204f.js +0 -0
  162. /package/dist/{static → standalone/packages/web/.next/static}/chunks/a45464b9776dd88e.js +0 -0
  163. /package/dist/{static → standalone/packages/web/.next/static}/chunks/a6dad97d9634a72d.js +0 -0
  164. /package/dist/{static → standalone/packages/web/.next/static}/chunks/ae04dcd433be6dab.js +0 -0
  165. /package/dist/{static → standalone/packages/web/.next/static}/chunks/b20313408e970968.css +0 -0
  166. /package/dist/{static → standalone/packages/web/.next/static}/chunks/c46095e1a421d93f.js +0 -0
  167. /package/dist/{static → standalone/packages/web/.next/static}/chunks/c48dd4c72d7c5ef4.js +0 -0
  168. /package/dist/{static → standalone/packages/web/.next/static}/chunks/c557ac675be79771.js +0 -0
  169. /package/dist/{static → standalone/packages/web/.next/static}/chunks/dca0c854c59234cd.js +0 -0
  170. /package/dist/{static → standalone/packages/web/.next/static}/chunks/df1731c03abf1aee.css +0 -0
  171. /package/dist/{static → standalone/packages/web/.next/static}/chunks/dfd41488ad062cd5.js +0 -0
  172. /package/dist/{static → standalone/packages/web/.next/static}/chunks/ebd89051637b9a47.js +0 -0
  173. /package/dist/{static → standalone/packages/web/.next/static}/chunks/f3ec9fd77a8618b1.js +0 -0
  174. /package/dist/{static → standalone/packages/web/.next/static}/chunks/turbopack-7450632b40b2e378.js +0 -0
  175. /package/dist/{public → standalone/packages/web/public}/f864aa7e7061c0600e35cf3d879b27cf.txt +0 -0
  176. /package/dist/{public → standalone/packages/web/public}/favicon.ico +0 -0
  177. /package/dist/{public → standalone/packages/web/public}/file.svg +0 -0
  178. /package/dist/{public → standalone/packages/web/public}/github-mark-white.svg +0 -0
  179. /package/dist/{public → standalone/packages/web/public}/github-mark.svg +0 -0
  180. /package/dist/{public → standalone/packages/web/public}/globe.svg +0 -0
  181. /package/dist/{public → standalone/packages/web/public}/icon.svg +0 -0
  182. /package/dist/{public → standalone/packages/web/public}/logo-dark-bg.svg +0 -0
  183. /package/dist/{public → standalone/packages/web/public}/logo-with-bg.svg +0 -0
  184. /package/dist/{public → standalone/packages/web/public}/logo.svg +0 -0
  185. /package/dist/{public → standalone/packages/web/public}/next.svg +0 -0
  186. /package/dist/{public → standalone/packages/web/public}/vercel.svg +0 -0
  187. /package/dist/{public → standalone/packages/web/public}/window.svg +0 -0
@@ -0,0 +1,436 @@
1
+ {
2
+ "version": "6",
3
+ "dialect": "sqlite",
4
+ "id": "ec23b6df-c408-4191-9d40-af9734fbc74f",
5
+ "prevId": "bc833859-0471-4dc1-8cff-61ae749f4a6c",
6
+ "tables": {
7
+ "projects": {
8
+ "name": "projects",
9
+ "columns": {
10
+ "id": {
11
+ "name": "id",
12
+ "type": "text",
13
+ "primaryKey": true,
14
+ "notNull": true,
15
+ "autoincrement": false
16
+ },
17
+ "github_owner": {
18
+ "name": "github_owner",
19
+ "type": "text",
20
+ "primaryKey": false,
21
+ "notNull": true,
22
+ "autoincrement": false
23
+ },
24
+ "github_repo": {
25
+ "name": "github_repo",
26
+ "type": "text",
27
+ "primaryKey": false,
28
+ "notNull": true,
29
+ "autoincrement": false
30
+ },
31
+ "display_name": {
32
+ "name": "display_name",
33
+ "type": "text",
34
+ "primaryKey": false,
35
+ "notNull": false,
36
+ "autoincrement": false
37
+ },
38
+ "description": {
39
+ "name": "description",
40
+ "type": "text",
41
+ "primaryKey": false,
42
+ "notNull": false,
43
+ "autoincrement": false
44
+ },
45
+ "homepage_url": {
46
+ "name": "homepage_url",
47
+ "type": "text",
48
+ "primaryKey": false,
49
+ "notNull": false,
50
+ "autoincrement": false
51
+ },
52
+ "stars": {
53
+ "name": "stars",
54
+ "type": "integer",
55
+ "primaryKey": false,
56
+ "notNull": false,
57
+ "autoincrement": false,
58
+ "default": 0
59
+ },
60
+ "is_public": {
61
+ "name": "is_public",
62
+ "type": "integer",
63
+ "primaryKey": false,
64
+ "notNull": false,
65
+ "autoincrement": false,
66
+ "default": true
67
+ },
68
+ "is_featured": {
69
+ "name": "is_featured",
70
+ "type": "integer",
71
+ "primaryKey": false,
72
+ "notNull": false,
73
+ "autoincrement": false,
74
+ "default": false
75
+ },
76
+ "last_synced_at": {
77
+ "name": "last_synced_at",
78
+ "type": "integer",
79
+ "primaryKey": false,
80
+ "notNull": false,
81
+ "autoincrement": false
82
+ },
83
+ "created_at": {
84
+ "name": "created_at",
85
+ "type": "integer",
86
+ "primaryKey": false,
87
+ "notNull": true,
88
+ "autoincrement": false
89
+ },
90
+ "updated_at": {
91
+ "name": "updated_at",
92
+ "type": "integer",
93
+ "primaryKey": false,
94
+ "notNull": true,
95
+ "autoincrement": false
96
+ }
97
+ },
98
+ "indexes": {},
99
+ "foreignKeys": {},
100
+ "compositePrimaryKeys": {},
101
+ "uniqueConstraints": {},
102
+ "checkConstraints": {}
103
+ },
104
+ "spec_relationships": {
105
+ "name": "spec_relationships",
106
+ "columns": {
107
+ "id": {
108
+ "name": "id",
109
+ "type": "text",
110
+ "primaryKey": true,
111
+ "notNull": true,
112
+ "autoincrement": false
113
+ },
114
+ "spec_id": {
115
+ "name": "spec_id",
116
+ "type": "text",
117
+ "primaryKey": false,
118
+ "notNull": true,
119
+ "autoincrement": false
120
+ },
121
+ "related_spec_id": {
122
+ "name": "related_spec_id",
123
+ "type": "text",
124
+ "primaryKey": false,
125
+ "notNull": true,
126
+ "autoincrement": false
127
+ },
128
+ "relationship_type": {
129
+ "name": "relationship_type",
130
+ "type": "text",
131
+ "primaryKey": false,
132
+ "notNull": true,
133
+ "autoincrement": false
134
+ },
135
+ "created_at": {
136
+ "name": "created_at",
137
+ "type": "integer",
138
+ "primaryKey": false,
139
+ "notNull": true,
140
+ "autoincrement": false
141
+ }
142
+ },
143
+ "indexes": {},
144
+ "foreignKeys": {
145
+ "spec_relationships_spec_id_specs_id_fk": {
146
+ "name": "spec_relationships_spec_id_specs_id_fk",
147
+ "tableFrom": "spec_relationships",
148
+ "tableTo": "specs",
149
+ "columnsFrom": [
150
+ "spec_id"
151
+ ],
152
+ "columnsTo": [
153
+ "id"
154
+ ],
155
+ "onDelete": "cascade",
156
+ "onUpdate": "no action"
157
+ },
158
+ "spec_relationships_related_spec_id_specs_id_fk": {
159
+ "name": "spec_relationships_related_spec_id_specs_id_fk",
160
+ "tableFrom": "spec_relationships",
161
+ "tableTo": "specs",
162
+ "columnsFrom": [
163
+ "related_spec_id"
164
+ ],
165
+ "columnsTo": [
166
+ "id"
167
+ ],
168
+ "onDelete": "cascade",
169
+ "onUpdate": "no action"
170
+ }
171
+ },
172
+ "compositePrimaryKeys": {},
173
+ "uniqueConstraints": {},
174
+ "checkConstraints": {}
175
+ },
176
+ "specs": {
177
+ "name": "specs",
178
+ "columns": {
179
+ "id": {
180
+ "name": "id",
181
+ "type": "text",
182
+ "primaryKey": true,
183
+ "notNull": true,
184
+ "autoincrement": false
185
+ },
186
+ "project_id": {
187
+ "name": "project_id",
188
+ "type": "text",
189
+ "primaryKey": false,
190
+ "notNull": true,
191
+ "autoincrement": false
192
+ },
193
+ "spec_number": {
194
+ "name": "spec_number",
195
+ "type": "integer",
196
+ "primaryKey": false,
197
+ "notNull": false,
198
+ "autoincrement": false
199
+ },
200
+ "spec_name": {
201
+ "name": "spec_name",
202
+ "type": "text",
203
+ "primaryKey": false,
204
+ "notNull": true,
205
+ "autoincrement": false
206
+ },
207
+ "title": {
208
+ "name": "title",
209
+ "type": "text",
210
+ "primaryKey": false,
211
+ "notNull": false,
212
+ "autoincrement": false
213
+ },
214
+ "status": {
215
+ "name": "status",
216
+ "type": "text",
217
+ "primaryKey": false,
218
+ "notNull": false,
219
+ "autoincrement": false
220
+ },
221
+ "priority": {
222
+ "name": "priority",
223
+ "type": "text",
224
+ "primaryKey": false,
225
+ "notNull": false,
226
+ "autoincrement": false
227
+ },
228
+ "tags": {
229
+ "name": "tags",
230
+ "type": "text",
231
+ "primaryKey": false,
232
+ "notNull": false,
233
+ "autoincrement": false
234
+ },
235
+ "assignee": {
236
+ "name": "assignee",
237
+ "type": "text",
238
+ "primaryKey": false,
239
+ "notNull": false,
240
+ "autoincrement": false
241
+ },
242
+ "content_md": {
243
+ "name": "content_md",
244
+ "type": "text",
245
+ "primaryKey": false,
246
+ "notNull": true,
247
+ "autoincrement": false
248
+ },
249
+ "content_html": {
250
+ "name": "content_html",
251
+ "type": "text",
252
+ "primaryKey": false,
253
+ "notNull": false,
254
+ "autoincrement": false
255
+ },
256
+ "created_at": {
257
+ "name": "created_at",
258
+ "type": "integer",
259
+ "primaryKey": false,
260
+ "notNull": false,
261
+ "autoincrement": false
262
+ },
263
+ "updated_at": {
264
+ "name": "updated_at",
265
+ "type": "integer",
266
+ "primaryKey": false,
267
+ "notNull": false,
268
+ "autoincrement": false
269
+ },
270
+ "completed_at": {
271
+ "name": "completed_at",
272
+ "type": "integer",
273
+ "primaryKey": false,
274
+ "notNull": false,
275
+ "autoincrement": false
276
+ },
277
+ "file_path": {
278
+ "name": "file_path",
279
+ "type": "text",
280
+ "primaryKey": false,
281
+ "notNull": true,
282
+ "autoincrement": false
283
+ },
284
+ "github_url": {
285
+ "name": "github_url",
286
+ "type": "text",
287
+ "primaryKey": false,
288
+ "notNull": false,
289
+ "autoincrement": false
290
+ },
291
+ "synced_at": {
292
+ "name": "synced_at",
293
+ "type": "integer",
294
+ "primaryKey": false,
295
+ "notNull": true,
296
+ "autoincrement": false
297
+ }
298
+ },
299
+ "indexes": {
300
+ "unique_spec_number": {
301
+ "name": "unique_spec_number",
302
+ "columns": [
303
+ "project_id",
304
+ "spec_number"
305
+ ],
306
+ "isUnique": true
307
+ }
308
+ },
309
+ "foreignKeys": {
310
+ "specs_project_id_projects_id_fk": {
311
+ "name": "specs_project_id_projects_id_fk",
312
+ "tableFrom": "specs",
313
+ "tableTo": "projects",
314
+ "columnsFrom": [
315
+ "project_id"
316
+ ],
317
+ "columnsTo": [
318
+ "id"
319
+ ],
320
+ "onDelete": "cascade",
321
+ "onUpdate": "no action"
322
+ }
323
+ },
324
+ "compositePrimaryKeys": {},
325
+ "uniqueConstraints": {},
326
+ "checkConstraints": {}
327
+ },
328
+ "sync_logs": {
329
+ "name": "sync_logs",
330
+ "columns": {
331
+ "id": {
332
+ "name": "id",
333
+ "type": "text",
334
+ "primaryKey": true,
335
+ "notNull": true,
336
+ "autoincrement": false
337
+ },
338
+ "project_id": {
339
+ "name": "project_id",
340
+ "type": "text",
341
+ "primaryKey": false,
342
+ "notNull": true,
343
+ "autoincrement": false
344
+ },
345
+ "status": {
346
+ "name": "status",
347
+ "type": "text",
348
+ "primaryKey": false,
349
+ "notNull": true,
350
+ "autoincrement": false
351
+ },
352
+ "specs_added": {
353
+ "name": "specs_added",
354
+ "type": "integer",
355
+ "primaryKey": false,
356
+ "notNull": false,
357
+ "autoincrement": false,
358
+ "default": 0
359
+ },
360
+ "specs_updated": {
361
+ "name": "specs_updated",
362
+ "type": "integer",
363
+ "primaryKey": false,
364
+ "notNull": false,
365
+ "autoincrement": false,
366
+ "default": 0
367
+ },
368
+ "specs_deleted": {
369
+ "name": "specs_deleted",
370
+ "type": "integer",
371
+ "primaryKey": false,
372
+ "notNull": false,
373
+ "autoincrement": false,
374
+ "default": 0
375
+ },
376
+ "error_message": {
377
+ "name": "error_message",
378
+ "type": "text",
379
+ "primaryKey": false,
380
+ "notNull": false,
381
+ "autoincrement": false
382
+ },
383
+ "started_at": {
384
+ "name": "started_at",
385
+ "type": "integer",
386
+ "primaryKey": false,
387
+ "notNull": true,
388
+ "autoincrement": false
389
+ },
390
+ "completed_at": {
391
+ "name": "completed_at",
392
+ "type": "integer",
393
+ "primaryKey": false,
394
+ "notNull": false,
395
+ "autoincrement": false
396
+ },
397
+ "duration_ms": {
398
+ "name": "duration_ms",
399
+ "type": "integer",
400
+ "primaryKey": false,
401
+ "notNull": false,
402
+ "autoincrement": false
403
+ }
404
+ },
405
+ "indexes": {},
406
+ "foreignKeys": {
407
+ "sync_logs_project_id_projects_id_fk": {
408
+ "name": "sync_logs_project_id_projects_id_fk",
409
+ "tableFrom": "sync_logs",
410
+ "tableTo": "projects",
411
+ "columnsFrom": [
412
+ "project_id"
413
+ ],
414
+ "columnsTo": [
415
+ "id"
416
+ ],
417
+ "onDelete": "cascade",
418
+ "onUpdate": "no action"
419
+ }
420
+ },
421
+ "compositePrimaryKeys": {},
422
+ "uniqueConstraints": {},
423
+ "checkConstraints": {}
424
+ }
425
+ },
426
+ "views": {},
427
+ "enums": {},
428
+ "_meta": {
429
+ "schemas": {},
430
+ "tables": {},
431
+ "columns": {}
432
+ },
433
+ "internal": {
434
+ "indexes": {}
435
+ }
436
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "sqlite",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "6",
8
+ "when": 1762872672477,
9
+ "tag": "0000_reflective_thena",
10
+ "breakpoints": true
11
+ },
12
+ {
13
+ "idx": 1,
14
+ "version": "6",
15
+ "when": 1762915233520,
16
+ "tag": "0001_fresh_carmella_unuscione",
17
+ "breakpoints": true
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,10 @@
1
+ import type { Config } from 'drizzle-kit';
2
+
3
+ export default {
4
+ schema: './src/lib/db/schema.ts',
5
+ out: './drizzle',
6
+ dialect: 'sqlite',
7
+ dbCredentials: {
8
+ url: process.env.DATABASE_PATH || './leanspec.db',
9
+ },
10
+ } satisfies Config;
@@ -0,0 +1,18 @@
1
+ import { defineConfig, globalIgnores } from "eslint/config";
2
+ import nextVitals from "eslint-config-next/core-web-vitals";
3
+ import nextTs from "eslint-config-next/typescript";
4
+
5
+ const eslintConfig = defineConfig([
6
+ ...nextVitals,
7
+ ...nextTs,
8
+ // Override default ignores of eslint-config-next.
9
+ globalIgnores([
10
+ // Default ignores of eslint-config-next:
11
+ ".next/**",
12
+ "out/**",
13
+ "build/**",
14
+ "next-env.d.ts",
15
+ ]),
16
+ ]);
17
+
18
+ export default eslintConfig;
@@ -0,0 +1,7 @@
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ output: 'standalone',
5
+ };
6
+
7
+ export default nextConfig;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leanspec/web",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "LeanSpec Web: Fullstack spec showcase platform",
5
5
  "private": true,
6
6
  "type": "module",
@@ -0,0 +1,8 @@
1
+ const config = {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
7
+
8
+ export default config;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * GET /api/projects/[id]/specs - Get specs for a project
3
+ */
4
+
5
+ import { NextResponse } from 'next/server';
6
+ import { getSpecsByProjectId } from '@/lib/db/queries';
7
+
8
+ export async function GET(
9
+ request: Request,
10
+ { params }: { params: Promise<{ id: string }> }
11
+ ) {
12
+ try {
13
+ const { id } = await params;
14
+ const specs = await getSpecsByProjectId(id);
15
+ return NextResponse.json({ specs });
16
+ } catch (error) {
17
+ console.error('Error fetching specs:', error);
18
+ return NextResponse.json(
19
+ { error: 'Failed to fetch specs' },
20
+ { status: 500 }
21
+ );
22
+ }
23
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * GET /api/projects - List all projects
3
+ */
4
+
5
+ import { NextResponse } from 'next/server';
6
+ import { getProjects } from '@/lib/db/queries';
7
+
8
+ export async function GET() {
9
+ try {
10
+ const projects = await getProjects();
11
+ return NextResponse.json({ projects });
12
+ } catch (error) {
13
+ console.error('Error fetching projects:', error);
14
+ return NextResponse.json(
15
+ { error: 'Failed to fetch projects' },
16
+ { status: 500 }
17
+ );
18
+ }
19
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * POST /api/revalidate - Cache invalidation endpoint
3
+ *
4
+ * Invalidates the in-memory cache for filesystem mode.
5
+ * Requires authentication via REVALIDATION_SECRET.
6
+ *
7
+ * Usage:
8
+ * POST /api/revalidate
9
+ * Body: { "secret": "your-secret", "specPath": "082" }
10
+ *
11
+ * Examples:
12
+ * - Invalidate specific spec: { "secret": "...", "specPath": "082" }
13
+ * - Invalidate all specs: { "secret": "..." }
14
+ */
15
+
16
+ import { NextResponse } from 'next/server';
17
+ import { specsService } from '@/lib/specs/service';
18
+ import { revalidatePath } from 'next/cache';
19
+
20
+ export async function POST(request: Request) {
21
+ try {
22
+ const { secret, specPath } = await request.json();
23
+
24
+ // Verify secret
25
+ const expectedSecret = process.env.REVALIDATION_SECRET;
26
+ if (!expectedSecret) {
27
+ return NextResponse.json(
28
+ { error: 'Revalidation not configured' },
29
+ { status: 503 }
30
+ );
31
+ }
32
+
33
+ if (secret !== expectedSecret) {
34
+ return NextResponse.json(
35
+ { error: 'Unauthorized' },
36
+ { status: 401 }
37
+ );
38
+ }
39
+
40
+ // Invalidate cache
41
+ await specsService.invalidateCache(specPath);
42
+
43
+ // Also revalidate Next.js cache
44
+ if (specPath) {
45
+ revalidatePath(`/specs/${specPath}`);
46
+ } else {
47
+ revalidatePath('/specs');
48
+ revalidatePath('/');
49
+ }
50
+
51
+ return NextResponse.json({
52
+ revalidated: true,
53
+ specPath: specPath || 'all',
54
+ timestamp: new Date().toISOString(),
55
+ });
56
+ } catch (error) {
57
+ console.error('Error revalidating cache:', error);
58
+ return NextResponse.json(
59
+ { error: 'Failed to revalidate cache' },
60
+ { status: 500 }
61
+ );
62
+ }
63
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Test the dependency-graph API endpoint
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest';
6
+ import { GET } from './route';
7
+ import { NextRequest } from 'next/server';
8
+
9
+ describe('Dependency Graph API', () => {
10
+ it('should return complete dependency graph for spec 097', async () => {
11
+ // Mock params
12
+ const params = Promise.resolve({ id: '097' });
13
+
14
+ // Create mock request
15
+ const request = new Request('http://localhost:3000/api/specs/097/dependency-graph');
16
+
17
+ // Call the endpoint
18
+ const response = await GET(request, { params });
19
+
20
+ // Parse response
21
+ const data = await response.json();
22
+
23
+ // If spec not found in test environment, skip detailed assertions
24
+ if (response.status === 404) {
25
+ expect(data).toHaveProperty('error');
26
+ return;
27
+ }
28
+
29
+ // Verify structure
30
+ expect(data).toHaveProperty('current');
31
+ expect(data).toHaveProperty('dependsOn');
32
+ expect(data).toHaveProperty('requiredBy');
33
+ expect(data).toHaveProperty('related');
34
+
35
+ // Verify arrays
36
+ expect(data.dependsOn).toBeInstanceOf(Array);
37
+ expect(data.requiredBy).toBeInstanceOf(Array);
38
+ expect(data.related).toBeInstanceOf(Array);
39
+ });
40
+
41
+ it('should return 404 for non-existent spec', async () => {
42
+ const params = Promise.resolve({ id: '999' });
43
+ const request = new Request('http://localhost:3000/api/specs/999/dependency-graph');
44
+
45
+ const response = await GET(request, { params });
46
+
47
+ expect(response.status).toBe(404);
48
+ const data = await response.json();
49
+ expect(data).toHaveProperty('error');
50
+ });
51
+ });