@selvajs/local-provider 0.11.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 (295) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +123 -0
  3. package/dist/auth/LocalAuthProvider.d.ts +28 -0
  4. package/dist/auth/LocalAuthProvider.d.ts.map +1 -0
  5. package/dist/auth/LocalAuthProvider.js +142 -0
  6. package/dist/auth/LocalAuthProvider.js.map +1 -0
  7. package/dist/auth/__tests__/conformance.test.d.ts +2 -0
  8. package/dist/auth/__tests__/conformance.test.d.ts.map +1 -0
  9. package/dist/auth/__tests__/conformance.test.js +36 -0
  10. package/dist/auth/__tests__/conformance.test.js.map +1 -0
  11. package/dist/auth/hmac.d.ts +18 -0
  12. package/dist/auth/hmac.d.ts.map +1 -0
  13. package/dist/auth/hmac.js +41 -0
  14. package/dist/auth/hmac.js.map +1 -0
  15. package/dist/auth/index.d.ts +6 -0
  16. package/dist/auth/index.d.ts.map +1 -0
  17. package/dist/auth/index.js +4 -0
  18. package/dist/auth/index.js.map +1 -0
  19. package/dist/auth/users.d.ts +38 -0
  20. package/dist/auth/users.d.ts.map +1 -0
  21. package/dist/auth/users.js +100 -0
  22. package/dist/auth/users.js.map +1 -0
  23. package/dist/compute/FilesystemComputeProvider.d.ts +16 -0
  24. package/dist/compute/FilesystemComputeProvider.d.ts.map +1 -0
  25. package/dist/compute/FilesystemComputeProvider.js +51 -0
  26. package/dist/compute/FilesystemComputeProvider.js.map +1 -0
  27. package/dist/compute/SingleComputeServerProvider.d.ts +15 -0
  28. package/dist/compute/SingleComputeServerProvider.d.ts.map +1 -0
  29. package/dist/compute/SingleComputeServerProvider.js +26 -0
  30. package/dist/compute/SingleComputeServerProvider.js.map +1 -0
  31. package/dist/compute/types.d.ts +30 -0
  32. package/dist/compute/types.d.ts.map +1 -0
  33. package/dist/compute/types.js +2 -0
  34. package/dist/compute/types.js.map +1 -0
  35. package/dist/computeServer/FilesystemComputeServerStore.d.ts +14 -0
  36. package/dist/computeServer/FilesystemComputeServerStore.d.ts.map +1 -0
  37. package/dist/computeServer/FilesystemComputeServerStore.js +35 -0
  38. package/dist/computeServer/FilesystemComputeServerStore.js.map +1 -0
  39. package/dist/computeServer/LocalComputeServerProvider.d.ts +18 -0
  40. package/dist/computeServer/LocalComputeServerProvider.d.ts.map +1 -0
  41. package/dist/computeServer/LocalComputeServerProvider.js +29 -0
  42. package/dist/computeServer/LocalComputeServerProvider.js.map +1 -0
  43. package/dist/computeServer/__tests__/conformance.test.d.ts +2 -0
  44. package/dist/computeServer/__tests__/conformance.test.d.ts.map +1 -0
  45. package/dist/computeServer/__tests__/conformance.test.js +20 -0
  46. package/dist/computeServer/__tests__/conformance.test.js.map +1 -0
  47. package/dist/computeServer/index.d.ts +2 -0
  48. package/dist/computeServer/index.d.ts.map +1 -0
  49. package/dist/computeServer/index.js +2 -0
  50. package/dist/computeServer/index.js.map +1 -0
  51. package/dist/data/LocalComputeServerStore.d.ts +72 -0
  52. package/dist/data/LocalComputeServerStore.d.ts.map +1 -0
  53. package/dist/data/LocalComputeServerStore.js +207 -0
  54. package/dist/data/LocalComputeServerStore.js.map +1 -0
  55. package/dist/data/LocalDataProvider.d.ts +47 -0
  56. package/dist/data/LocalDataProvider.d.ts.map +1 -0
  57. package/dist/data/LocalDataProvider.js +118 -0
  58. package/dist/data/LocalDataProvider.js.map +1 -0
  59. package/dist/data/LocalDefinitionMetaProvider.d.ts +22 -0
  60. package/dist/data/LocalDefinitionMetaProvider.d.ts.map +1 -0
  61. package/dist/data/LocalDefinitionMetaProvider.js +131 -0
  62. package/dist/data/LocalDefinitionMetaProvider.js.map +1 -0
  63. package/dist/data/LocalDefinitionStore.d.ts +33 -0
  64. package/dist/data/LocalDefinitionStore.d.ts.map +1 -0
  65. package/dist/data/LocalDefinitionStore.js +274 -0
  66. package/dist/data/LocalDefinitionStore.js.map +1 -0
  67. package/dist/data/LocalInviteStore.d.ts +23 -0
  68. package/dist/data/LocalInviteStore.d.ts.map +1 -0
  69. package/dist/data/LocalInviteStore.js +98 -0
  70. package/dist/data/LocalInviteStore.js.map +1 -0
  71. package/dist/data/LocalOrgStore.d.ts +67 -0
  72. package/dist/data/LocalOrgStore.d.ts.map +1 -0
  73. package/dist/data/LocalOrgStore.js +255 -0
  74. package/dist/data/LocalOrgStore.js.map +1 -0
  75. package/dist/data/LocalPlatformProjectGrantStore.d.ts +14 -0
  76. package/dist/data/LocalPlatformProjectGrantStore.d.ts.map +1 -0
  77. package/dist/data/LocalPlatformProjectGrantStore.js +62 -0
  78. package/dist/data/LocalPlatformProjectGrantStore.js.map +1 -0
  79. package/dist/data/LocalProjectStore.d.ts +30 -0
  80. package/dist/data/LocalProjectStore.d.ts.map +1 -0
  81. package/dist/data/LocalProjectStore.js +171 -0
  82. package/dist/data/LocalProjectStore.js.map +1 -0
  83. package/dist/data/LocalShareLinkStore.d.ts +39 -0
  84. package/dist/data/LocalShareLinkStore.d.ts.map +1 -0
  85. package/dist/data/LocalShareLinkStore.js +108 -0
  86. package/dist/data/LocalShareLinkStore.js.map +1 -0
  87. package/dist/data/__tests__/LocalDefinitionMetaProvider.test.d.ts +2 -0
  88. package/dist/data/__tests__/LocalDefinitionMetaProvider.test.d.ts.map +1 -0
  89. package/dist/data/__tests__/LocalDefinitionMetaProvider.test.js +21 -0
  90. package/dist/data/__tests__/LocalDefinitionMetaProvider.test.js.map +1 -0
  91. package/dist/data/__tests__/cascade.test.d.ts +2 -0
  92. package/dist/data/__tests__/cascade.test.d.ts.map +1 -0
  93. package/dist/data/__tests__/cascade.test.js +265 -0
  94. package/dist/data/__tests__/cascade.test.js.map +1 -0
  95. package/dist/data/__tests__/compute-server-conformance.test.d.ts +2 -0
  96. package/dist/data/__tests__/compute-server-conformance.test.d.ts.map +1 -0
  97. package/dist/data/__tests__/compute-server-conformance.test.js +21 -0
  98. package/dist/data/__tests__/compute-server-conformance.test.js.map +1 -0
  99. package/dist/data/__tests__/compute-server-encryption.test.d.ts +2 -0
  100. package/dist/data/__tests__/compute-server-encryption.test.d.ts.map +1 -0
  101. package/dist/data/__tests__/compute-server-encryption.test.js +131 -0
  102. package/dist/data/__tests__/compute-server-encryption.test.js.map +1 -0
  103. package/dist/data/__tests__/definition-conformance.test.d.ts +2 -0
  104. package/dist/data/__tests__/definition-conformance.test.d.ts.map +1 -0
  105. package/dist/data/__tests__/definition-conformance.test.js +20 -0
  106. package/dist/data/__tests__/definition-conformance.test.js.map +1 -0
  107. package/dist/data/__tests__/event-sink-conformance.test.d.ts +2 -0
  108. package/dist/data/__tests__/event-sink-conformance.test.d.ts.map +1 -0
  109. package/dist/data/__tests__/event-sink-conformance.test.js +24 -0
  110. package/dist/data/__tests__/event-sink-conformance.test.js.map +1 -0
  111. package/dist/data/__tests__/invite-conformance.test.d.ts +2 -0
  112. package/dist/data/__tests__/invite-conformance.test.d.ts.map +1 -0
  113. package/dist/data/__tests__/invite-conformance.test.js +21 -0
  114. package/dist/data/__tests__/invite-conformance.test.js.map +1 -0
  115. package/dist/data/__tests__/org-conformance.test.d.ts +2 -0
  116. package/dist/data/__tests__/org-conformance.test.d.ts.map +1 -0
  117. package/dist/data/__tests__/org-conformance.test.js +36 -0
  118. package/dist/data/__tests__/org-conformance.test.js.map +1 -0
  119. package/dist/data/__tests__/platform-project-grant-conformance.test.d.ts +2 -0
  120. package/dist/data/__tests__/platform-project-grant-conformance.test.d.ts.map +1 -0
  121. package/dist/data/__tests__/platform-project-grant-conformance.test.js +20 -0
  122. package/dist/data/__tests__/platform-project-grant-conformance.test.js.map +1 -0
  123. package/dist/data/__tests__/project-conformance.test.d.ts +2 -0
  124. package/dist/data/__tests__/project-conformance.test.d.ts.map +1 -0
  125. package/dist/data/__tests__/project-conformance.test.js +53 -0
  126. package/dist/data/__tests__/project-conformance.test.js.map +1 -0
  127. package/dist/data/__tests__/rules.test.d.ts +2 -0
  128. package/dist/data/__tests__/rules.test.d.ts.map +1 -0
  129. package/dist/data/__tests__/rules.test.js +484 -0
  130. package/dist/data/__tests__/rules.test.js.map +1 -0
  131. package/dist/data/__tests__/share-link-conformance.test.d.ts +2 -0
  132. package/dist/data/__tests__/share-link-conformance.test.d.ts.map +1 -0
  133. package/dist/data/__tests__/share-link-conformance.test.js +20 -0
  134. package/dist/data/__tests__/share-link-conformance.test.js.map +1 -0
  135. package/dist/data/fsJson.d.ts +12 -0
  136. package/dist/data/fsJson.d.ts.map +1 -0
  137. package/dist/data/fsJson.js +29 -0
  138. package/dist/data/fsJson.js.map +1 -0
  139. package/dist/data/index.d.ts +13 -0
  140. package/dist/data/index.d.ts.map +1 -0
  141. package/dist/data/index.js +9 -0
  142. package/dist/data/index.js.map +1 -0
  143. package/dist/data/pagination.d.ts +15 -0
  144. package/dist/data/pagination.d.ts.map +1 -0
  145. package/dist/data/pagination.js +36 -0
  146. package/dist/data/pagination.js.map +1 -0
  147. package/dist/data/secretCrypto.d.ts +23 -0
  148. package/dist/data/secretCrypto.d.ts.map +1 -0
  149. package/dist/data/secretCrypto.js +64 -0
  150. package/dist/data/secretCrypto.js.map +1 -0
  151. package/dist/data/userData.d.ts +40 -0
  152. package/dist/data/userData.d.ts.map +1 -0
  153. package/dist/data/userData.js +84 -0
  154. package/dist/data/userData.js.map +1 -0
  155. package/dist/definitions/LocalDefinitionMetaProvider.d.ts +27 -0
  156. package/dist/definitions/LocalDefinitionMetaProvider.d.ts.map +1 -0
  157. package/dist/definitions/LocalDefinitionMetaProvider.js +188 -0
  158. package/dist/definitions/LocalDefinitionMetaProvider.js.map +1 -0
  159. package/dist/definitions/__tests__/conformance.test.d.ts +2 -0
  160. package/dist/definitions/__tests__/conformance.test.d.ts.map +1 -0
  161. package/dist/definitions/__tests__/conformance.test.js +20 -0
  162. package/dist/definitions/__tests__/conformance.test.js.map +1 -0
  163. package/dist/definitions/index.d.ts +2 -0
  164. package/dist/definitions/index.d.ts.map +1 -0
  165. package/dist/definitions/index.js +2 -0
  166. package/dist/definitions/index.js.map +1 -0
  167. package/dist/definitions/providers/filesystem-files.d.ts +24 -0
  168. package/dist/definitions/providers/filesystem-files.d.ts.map +1 -0
  169. package/dist/definitions/providers/filesystem-files.js +170 -0
  170. package/dist/definitions/providers/filesystem-files.js.map +1 -0
  171. package/dist/definitions/providers/filesystem-meta.d.ts +17 -0
  172. package/dist/definitions/providers/filesystem-meta.d.ts.map +1 -0
  173. package/dist/definitions/providers/filesystem-meta.js +216 -0
  174. package/dist/definitions/providers/filesystem-meta.js.map +1 -0
  175. package/dist/fsJson.d.ts +12 -0
  176. package/dist/fsJson.d.ts.map +1 -0
  177. package/dist/fsJson.js +29 -0
  178. package/dist/fsJson.js.map +1 -0
  179. package/dist/index.d.ts +13 -0
  180. package/dist/index.d.ts.map +1 -0
  181. package/dist/index.js +16 -0
  182. package/dist/index.js.map +1 -0
  183. package/dist/invites/LocalInviteProvider.d.ts +24 -0
  184. package/dist/invites/LocalInviteProvider.d.ts.map +1 -0
  185. package/dist/invites/LocalInviteProvider.js +89 -0
  186. package/dist/invites/LocalInviteProvider.js.map +1 -0
  187. package/dist/invites/__tests__/conformance.test.d.ts +2 -0
  188. package/dist/invites/__tests__/conformance.test.d.ts.map +1 -0
  189. package/dist/invites/__tests__/conformance.test.js +21 -0
  190. package/dist/invites/__tests__/conformance.test.js.map +1 -0
  191. package/dist/organizations/LocalOrganizationProvider.d.ts +41 -0
  192. package/dist/organizations/LocalOrganizationProvider.d.ts.map +1 -0
  193. package/dist/organizations/LocalOrganizationProvider.js +198 -0
  194. package/dist/organizations/LocalOrganizationProvider.js.map +1 -0
  195. package/dist/organizations/__tests__/conformance.test.d.ts +2 -0
  196. package/dist/organizations/__tests__/conformance.test.d.ts.map +1 -0
  197. package/dist/organizations/__tests__/conformance.test.js +20 -0
  198. package/dist/organizations/__tests__/conformance.test.js.map +1 -0
  199. package/dist/organizations/index.d.ts +2 -0
  200. package/dist/organizations/index.d.ts.map +1 -0
  201. package/dist/organizations/index.js +2 -0
  202. package/dist/organizations/index.js.map +1 -0
  203. package/dist/pagination.d.ts +15 -0
  204. package/dist/pagination.d.ts.map +1 -0
  205. package/dist/pagination.js +36 -0
  206. package/dist/pagination.js.map +1 -0
  207. package/dist/permissions/LocalPlatformPermissionStore.d.ts +39 -0
  208. package/dist/permissions/LocalPlatformPermissionStore.d.ts.map +1 -0
  209. package/dist/permissions/LocalPlatformPermissionStore.js +117 -0
  210. package/dist/permissions/LocalPlatformPermissionStore.js.map +1 -0
  211. package/dist/permissions/__tests__/conformance.test.d.ts +2 -0
  212. package/dist/permissions/__tests__/conformance.test.d.ts.map +1 -0
  213. package/dist/permissions/__tests__/conformance.test.js +37 -0
  214. package/dist/permissions/__tests__/conformance.test.js.map +1 -0
  215. package/dist/permissions/index.d.ts +2 -0
  216. package/dist/permissions/index.d.ts.map +1 -0
  217. package/dist/permissions/index.js +2 -0
  218. package/dist/permissions/index.js.map +1 -0
  219. package/dist/projects/LocalProjectProvider.d.ts +21 -0
  220. package/dist/projects/LocalProjectProvider.d.ts.map +1 -0
  221. package/dist/projects/LocalProjectProvider.js +125 -0
  222. package/dist/projects/LocalProjectProvider.js.map +1 -0
  223. package/dist/projects/__tests__/conformance.test.d.ts +2 -0
  224. package/dist/projects/__tests__/conformance.test.d.ts.map +1 -0
  225. package/dist/projects/__tests__/conformance.test.js +44 -0
  226. package/dist/projects/__tests__/conformance.test.js.map +1 -0
  227. package/dist/projects/index.d.ts +2 -0
  228. package/dist/projects/index.d.ts.map +1 -0
  229. package/dist/projects/index.js +2 -0
  230. package/dist/projects/index.js.map +1 -0
  231. package/dist/storage/LocalStorageProvider.d.ts +27 -0
  232. package/dist/storage/LocalStorageProvider.d.ts.map +1 -0
  233. package/dist/storage/LocalStorageProvider.js +74 -0
  234. package/dist/storage/LocalStorageProvider.js.map +1 -0
  235. package/dist/storage/__tests__/conformance.test.d.ts +2 -0
  236. package/dist/storage/__tests__/conformance.test.d.ts.map +1 -0
  237. package/dist/storage/__tests__/conformance.test.js +20 -0
  238. package/dist/storage/__tests__/conformance.test.js.map +1 -0
  239. package/dist/storage/index.d.ts +2 -0
  240. package/dist/storage/index.d.ts.map +1 -0
  241. package/dist/storage/index.js +2 -0
  242. package/dist/storage/index.js.map +1 -0
  243. package/dist/userProfile/LocalUserProfileProvider.d.ts +25 -0
  244. package/dist/userProfile/LocalUserProfileProvider.d.ts.map +1 -0
  245. package/dist/userProfile/LocalUserProfileProvider.js +110 -0
  246. package/dist/userProfile/LocalUserProfileProvider.js.map +1 -0
  247. package/dist/userProfile/__tests__/conformance.test.d.ts +2 -0
  248. package/dist/userProfile/__tests__/conformance.test.d.ts.map +1 -0
  249. package/dist/userProfile/__tests__/conformance.test.js +40 -0
  250. package/dist/userProfile/__tests__/conformance.test.js.map +1 -0
  251. package/dist/userProfile/index.d.ts +2 -0
  252. package/dist/userProfile/index.d.ts.map +1 -0
  253. package/dist/userProfile/index.js +2 -0
  254. package/dist/userProfile/index.js.map +1 -0
  255. package/package.json +70 -0
  256. package/src/README.md +37 -0
  257. package/src/auth/LocalAuthProvider.ts +165 -0
  258. package/src/auth/__tests__/conformance.test.ts +40 -0
  259. package/src/auth/hmac.ts +53 -0
  260. package/src/auth/index.ts +5 -0
  261. package/src/auth/users.ts +151 -0
  262. package/src/data/LocalComputeServerStore.ts +290 -0
  263. package/src/data/LocalDataProvider.ts +148 -0
  264. package/src/data/LocalDefinitionStore.ts +369 -0
  265. package/src/data/LocalInviteStore.ts +117 -0
  266. package/src/data/LocalOrgStore.ts +356 -0
  267. package/src/data/LocalPlatformProjectGrantStore.ts +85 -0
  268. package/src/data/LocalProjectStore.ts +274 -0
  269. package/src/data/LocalShareLinkStore.ts +138 -0
  270. package/src/data/__tests__/cascade.test.ts +300 -0
  271. package/src/data/__tests__/compute-server-conformance.test.ts +26 -0
  272. package/src/data/__tests__/compute-server-encryption.test.ts +185 -0
  273. package/src/data/__tests__/definition-conformance.test.ts +23 -0
  274. package/src/data/__tests__/event-sink-conformance.test.ts +28 -0
  275. package/src/data/__tests__/invite-conformance.test.ts +24 -0
  276. package/src/data/__tests__/org-conformance.test.ts +43 -0
  277. package/src/data/__tests__/platform-project-grant-conformance.test.ts +24 -0
  278. package/src/data/__tests__/project-conformance.test.ts +64 -0
  279. package/src/data/__tests__/rules.test.ts +682 -0
  280. package/src/data/__tests__/share-link-conformance.test.ts +23 -0
  281. package/src/data/fsJson.ts +28 -0
  282. package/src/data/index.ts +16 -0
  283. package/src/data/pagination.ts +48 -0
  284. package/src/data/secretCrypto.ts +69 -0
  285. package/src/data/userData.ts +134 -0
  286. package/src/index.ts +42 -0
  287. package/src/permissions/LocalPlatformPermissionStore.ts +129 -0
  288. package/src/permissions/__tests__/conformance.test.ts +40 -0
  289. package/src/permissions/index.ts +1 -0
  290. package/src/storage/LocalStorageProvider.ts +78 -0
  291. package/src/storage/__tests__/conformance.test.ts +23 -0
  292. package/src/storage/index.ts +1 -0
  293. package/src/userProfile/LocalUserProfileProvider.ts +135 -0
  294. package/src/userProfile/__tests__/conformance.test.ts +43 -0
  295. package/src/userProfile/index.ts +1 -0
@@ -0,0 +1,170 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import sharp from 'sharp';
4
+ import { GH_EXTENSIONS, COVER_IMAGE_EXTENSIONS as ALLOWED_IMAGE_EXTENSIONS } from '@selva/platform/definitions';
5
+ export class LocalDefinitionFileProvider {
6
+ definitionsPath;
7
+ imageUrlPrefix;
8
+ constructor(definitionsPath, imageUrlPrefix = '/api/definitions') {
9
+ this.definitionsPath = definitionsPath;
10
+ this.imageUrlPrefix = imageUrlPrefix;
11
+ }
12
+ guidPath(guid) {
13
+ return path.join(this.definitionsPath, guid);
14
+ }
15
+ oldFilesDir(guid) {
16
+ return path.join(this.guidPath(guid), 'old_files');
17
+ }
18
+ // ── IDefinitionFileProvider ─────────────────────────────────────────────
19
+ async getFile(guid) {
20
+ const guidDir = this.guidPath(guid);
21
+ for (const ext of GH_EXTENSIONS) {
22
+ const filePath = path.join(guidDir, `definition${ext}`);
23
+ try {
24
+ const buffer = await fs.readFile(filePath);
25
+ return new Uint8Array(buffer);
26
+ }
27
+ catch {
28
+ // try next extension
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ async getPreviewImage(guid) {
34
+ // Read the coverImage field from the config to find the stored filename
35
+ const configPath = path.join(this.definitionsPath, 'definitions-config.json');
36
+ let coverImage;
37
+ try {
38
+ const content = await fs.readFile(configPath, 'utf-8');
39
+ const config = JSON.parse(content);
40
+ coverImage = config.definitions[guid]?.coverImage;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ if (!coverImage)
46
+ return null;
47
+ // Extract filename from the coverImage URL or path
48
+ const imageFilename = coverImage.split('/').pop();
49
+ if (!imageFilename)
50
+ return null;
51
+ const guidDir = this.guidPath(guid);
52
+ // Try the stored filename, then fall back to the .webp variant
53
+ const webpFilename = imageFilename.replace(/\.[^.]+$/, '.webp');
54
+ const candidates = imageFilename === webpFilename ? [imageFilename] : [imageFilename, webpFilename];
55
+ for (const candidate of candidates) {
56
+ try {
57
+ const buffer = await fs.readFile(path.join(guidDir, candidate));
58
+ return new Uint8Array(buffer);
59
+ }
60
+ catch {
61
+ // try next candidate
62
+ }
63
+ }
64
+ return null;
65
+ }
66
+ async getArchivedFile(guid, ref) {
67
+ const filePath = path.join(this.oldFilesDir(guid), ref);
68
+ try {
69
+ const buffer = await fs.readFile(filePath);
70
+ return new Uint8Array(buffer);
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ async saveFile(guid, data, ext) {
77
+ const guidDir = this.guidPath(guid);
78
+ await fs.mkdir(guidDir, { recursive: true });
79
+ // Delete any existing GH file with a different extension
80
+ for (const existingExt of GH_EXTENSIONS) {
81
+ if (existingExt !== `.${ext}`) {
82
+ try {
83
+ await fs.unlink(path.join(guidDir, `definition${existingExt}`));
84
+ }
85
+ catch {
86
+ // Non-fatal — file may not exist
87
+ }
88
+ }
89
+ }
90
+ await fs.writeFile(path.join(guidDir, `definition.${ext}`), Buffer.from(data));
91
+ }
92
+ async archiveCurrentFile(guid, originalName) {
93
+ const guidDir = this.guidPath(guid);
94
+ let currentFile = null;
95
+ try {
96
+ const entries = await fs.readdir(guidDir);
97
+ for (const entry of entries) {
98
+ const entryExt = path.extname(entry).toLowerCase();
99
+ if (entry !== 'old_files' && GH_EXTENSIONS.includes(entryExt)) {
100
+ currentFile = entry;
101
+ break;
102
+ }
103
+ }
104
+ }
105
+ catch {
106
+ return null;
107
+ }
108
+ if (!currentFile)
109
+ return null;
110
+ const oldDir = this.oldFilesDir(guid);
111
+ await fs.mkdir(oldDir, { recursive: true });
112
+ const now = new Date();
113
+ const timestamp = now.toISOString().replace(/[:.]/g, '-');
114
+ const backupName = `${timestamp}_${currentFile}`;
115
+ const data = await fs.readFile(path.join(guidDir, currentFile));
116
+ await fs.writeFile(path.join(oldDir, backupName), data);
117
+ await fs.unlink(path.join(guidDir, currentFile));
118
+ return {
119
+ ref: backupName,
120
+ originalName,
121
+ archivedAt: now.toISOString()
122
+ };
123
+ }
124
+ async deleteArchivedFile(guid, ref) {
125
+ try {
126
+ await fs.unlink(path.join(this.oldFilesDir(guid), ref));
127
+ }
128
+ catch {
129
+ // Non-fatal
130
+ }
131
+ }
132
+ /**
133
+ * Save a preview image compressed to WebP.
134
+ * Returns the public URL for the stored image (used by callers to update meta.coverImage).
135
+ * The return type is void per IDefinitionFileProvider — callers read the URL via getImageUrl().
136
+ */
137
+ async saveImage(guid, data) {
138
+ const guidDir = this.guidPath(guid);
139
+ await fs.mkdir(guidDir, { recursive: true });
140
+ // Always store as WebP
141
+ const filename = 'cover.webp';
142
+ const filePath = path.join(guidDir, filename);
143
+ const compressed = await sharp(Buffer.from(data))
144
+ .resize({ width: 1200, withoutEnlargement: true })
145
+ .webp({ quality: 85 })
146
+ .toBuffer();
147
+ await fs.writeFile(filePath, compressed);
148
+ // Delete any old image files (different name or extension)
149
+ try {
150
+ const entries = await fs.readdir(guidDir);
151
+ for (const entry of entries) {
152
+ if (entry !== filename &&
153
+ ALLOWED_IMAGE_EXTENSIONS.includes(path.extname(entry).toLowerCase())) {
154
+ await fs.rm(path.join(guidDir, entry), { force: true });
155
+ }
156
+ }
157
+ }
158
+ catch {
159
+ // Non-fatal
160
+ }
161
+ }
162
+ /** Returns the public URL for the stored cover image (always cover.webp). */
163
+ getCoverImageUrl(guid) {
164
+ return `${this.imageUrlPrefix}/${guid}/image/cover.webp`;
165
+ }
166
+ async deleteFiles(guid) {
167
+ await fs.rm(this.guidPath(guid), { recursive: true, force: true });
168
+ }
169
+ }
170
+ //# sourceMappingURL=filesystem-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem-files.js","sourceRoot":"","sources":["../../../src/definitions/providers/filesystem-files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { IDefinitionMetaProvider, DefinitionRecord, DefinitionMeta, HistoryEntry } from '@selva/platform/definitions';
2
+ export declare class LocalDefinitionMetaProvider implements IDefinitionMetaProvider {
3
+ private readonly configPath;
4
+ constructor(definitionsPath: string);
5
+ private readConfig;
6
+ private writeConfig;
7
+ list(): Promise<DefinitionRecord[]>;
8
+ listByProject(projectId: string): Promise<DefinitionRecord[]>;
9
+ listPublic(): Promise<DefinitionRecord[]>;
10
+ get(guid: string): Promise<DefinitionRecord | null>;
11
+ create(record: DefinitionRecord): Promise<void>;
12
+ update(guid: string, patch: Partial<DefinitionMeta>): Promise<void>;
13
+ addHistoryEntry(guid: string, entry: HistoryEntry): Promise<void>;
14
+ removeHistoryEntry(guid: string, ref: string): Promise<void>;
15
+ delete(guid: string): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=filesystem-meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem-meta.d.ts","sourceRoot":"","sources":["../../../src/definitions/providers/filesystem-meta.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EAEd,YAAY,EACZ,MAAM,6BAA6B,CAAC;AAuFrC,qBAAa,2BAA4B,YAAW,uBAAuB;IAC1E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,eAAe,EAAE,MAAM;YAMrB,UAAU;YAYV,WAAW;IAQnB,IAAI,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAanC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAK7D,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAMzC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAOnD,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB/C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA4CnE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBjE,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAKzC"}
@@ -0,0 +1,216 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ // Normalize admin image URLs to public URLs
4
+ function normalizeCoverImage(url) {
5
+ if (!url?.startsWith('/admin/api/definitions/'))
6
+ return url;
7
+ const match = url.match(/\/admin\/api\/definitions\/(.+?)\/(image\/.+)/);
8
+ if (match)
9
+ return `/api/definitions/${match[1]}/${match[2]}`;
10
+ return url;
11
+ }
12
+ // Map stored history entry (legacy filename/date fields) to platform HistoryEntry (ref/archivedAt)
13
+ function toHistoryEntry(stored) {
14
+ return {
15
+ ref: stored.filename,
16
+ originalName: stored.originalName,
17
+ archivedAt: stored.date
18
+ };
19
+ }
20
+ // Map platform HistoryEntry back to stored shape
21
+ function toStoredHistoryEntry(entry) {
22
+ return {
23
+ filename: entry.ref,
24
+ originalName: entry.originalName,
25
+ date: entry.archivedAt
26
+ };
27
+ }
28
+ function deriveFileExt(file) {
29
+ if (file?.endsWith('.ghx'))
30
+ return 'ghx';
31
+ return 'gh';
32
+ }
33
+ function toDefinitionRecord(guid, stored) {
34
+ const history = (stored.history ?? []).map(toHistoryEntry);
35
+ // Sort newest first
36
+ history.sort((a, b) => b.archivedAt.localeCompare(a.archivedAt));
37
+ return {
38
+ guid,
39
+ projectId: stored.projectId ?? '',
40
+ ownerId: stored.ownerId ?? '',
41
+ computeServerId: stored.computeServerId,
42
+ fileExt: deriveFileExt(stored.file),
43
+ meta: {
44
+ displayName: stored.displayName,
45
+ description: stored.description,
46
+ coverImage: normalizeCoverImage(stored.coverImage),
47
+ category: stored.category,
48
+ tags: stored.tags,
49
+ originalFilename: stored.originalFilename
50
+ },
51
+ history,
52
+ maxHistory: stored.maxHistory ?? 0,
53
+ createdAt: stored.createdAt ?? new Date(0).toISOString(),
54
+ updatedAt: stored.updatedAt ?? new Date(0).toISOString()
55
+ };
56
+ }
57
+ export class LocalDefinitionMetaProvider {
58
+ configPath;
59
+ constructor(definitionsPath) {
60
+ this.configPath = path.join(definitionsPath, 'definitions-config.json');
61
+ }
62
+ // ── Config helpers ──────────────────────────────────────────────────────
63
+ async readConfig() {
64
+ try {
65
+ const content = await fs.readFile(this.configPath, 'utf-8');
66
+ return JSON.parse(content);
67
+ }
68
+ catch (err) {
69
+ if (err.code === 'ENOENT') {
70
+ return { definitions: {} };
71
+ }
72
+ throw err;
73
+ }
74
+ }
75
+ async writeConfig(config) {
76
+ const tmpPath = `${this.configPath}.tmp`;
77
+ await fs.writeFile(tmpPath, JSON.stringify(config, null, '\t'), 'utf-8');
78
+ await fs.rename(tmpPath, this.configPath);
79
+ }
80
+ // ── IDefinitionMetaProvider ─────────────────────────────────────────────
81
+ async list() {
82
+ const config = await this.readConfig();
83
+ const records = [];
84
+ for (const [guid, stored] of Object.entries(config.definitions)) {
85
+ if (!stored.displayName)
86
+ continue;
87
+ records.push(toDefinitionRecord(guid, stored));
88
+ }
89
+ records.sort((a, b) => a.meta.displayName.localeCompare(b.meta.displayName));
90
+ return records;
91
+ }
92
+ async listByProject(projectId) {
93
+ const all = await this.list();
94
+ return all.filter((r) => r.projectId === projectId);
95
+ }
96
+ async listPublic() {
97
+ // Local provider has no project visibility concept — return all records.
98
+ // A real multi-tenant provider would join against project visibility here.
99
+ return this.list();
100
+ }
101
+ async get(guid) {
102
+ const config = await this.readConfig();
103
+ const stored = config.definitions[guid];
104
+ if (!stored)
105
+ return null;
106
+ return toDefinitionRecord(guid, stored);
107
+ }
108
+ async create(record) {
109
+ const config = await this.readConfig();
110
+ const entry = {
111
+ displayName: record.meta.displayName,
112
+ file: `definition.${record.fileExt}`,
113
+ originalFilename: record.meta.originalFilename,
114
+ history: [],
115
+ projectId: record.projectId,
116
+ ownerId: record.ownerId,
117
+ createdAt: record.createdAt,
118
+ updatedAt: record.updatedAt
119
+ };
120
+ if (record.computeServerId)
121
+ entry.computeServerId = record.computeServerId;
122
+ if (record.meta.description)
123
+ entry.description = record.meta.description;
124
+ if (record.meta.category)
125
+ entry.category = record.meta.category;
126
+ if (record.meta.tags && record.meta.tags.length > 0)
127
+ entry.tags = record.meta.tags;
128
+ if (record.meta.coverImage)
129
+ entry.coverImage = record.meta.coverImage;
130
+ if (record.maxHistory > 0)
131
+ entry.maxHistory = record.maxHistory;
132
+ config.definitions[record.guid] = entry;
133
+ await this.writeConfig(config);
134
+ }
135
+ async update(guid, patch) {
136
+ const config = await this.readConfig();
137
+ const existing = config.definitions[guid];
138
+ if (!existing)
139
+ throw new Error(`Definition '${guid}' not found`);
140
+ const updated = {
141
+ displayName: patch.displayName ?? existing.displayName,
142
+ file: existing.file || ''
143
+ };
144
+ if (existing.originalFilename)
145
+ updated.originalFilename = existing.originalFilename;
146
+ // String fields: patch overrides if provided; preserve existing otherwise
147
+ if (patch.description !== undefined) {
148
+ if (patch.description)
149
+ updated.description = patch.description;
150
+ }
151
+ else if (existing.description) {
152
+ updated.description = existing.description;
153
+ }
154
+ if (patch.category !== undefined) {
155
+ if (patch.category)
156
+ updated.category = patch.category;
157
+ }
158
+ else if (existing.category) {
159
+ updated.category = existing.category;
160
+ }
161
+ if (patch.tags !== undefined) {
162
+ if (patch.tags && patch.tags.length > 0)
163
+ updated.tags = patch.tags;
164
+ }
165
+ else if (existing.tags) {
166
+ updated.tags = existing.tags;
167
+ }
168
+ if (patch.coverImage !== undefined) {
169
+ if (patch.coverImage)
170
+ updated.coverImage = patch.coverImage;
171
+ }
172
+ else if (existing.coverImage) {
173
+ updated.coverImage = existing.coverImage;
174
+ }
175
+ if (existing.history !== undefined)
176
+ updated.history = existing.history;
177
+ if (existing.maxHistory !== undefined)
178
+ updated.maxHistory = existing.maxHistory;
179
+ config.definitions[guid] = updated;
180
+ await this.writeConfig(config);
181
+ }
182
+ async addHistoryEntry(guid, entry) {
183
+ const config = await this.readConfig();
184
+ const existing = config.definitions[guid];
185
+ if (!existing)
186
+ throw new Error(`Definition '${guid}' not found`);
187
+ const storedEntry = toStoredHistoryEntry(entry);
188
+ const history = [storedEntry, ...(existing.history ?? [])];
189
+ // Prune if maxHistory set — caller is responsible for deleting archived files
190
+ if (existing.maxHistory && existing.maxHistory > 0) {
191
+ existing.history = history.slice(0, existing.maxHistory);
192
+ }
193
+ else {
194
+ existing.history = history;
195
+ }
196
+ // Update originalFilename to reflect the new file being uploaded
197
+ // (caller should also update this via update() if needed)
198
+ config.definitions[guid] = existing;
199
+ await this.writeConfig(config);
200
+ }
201
+ async removeHistoryEntry(guid, ref) {
202
+ const config = await this.readConfig();
203
+ const existing = config.definitions[guid];
204
+ if (!existing)
205
+ throw new Error(`Definition '${guid}' not found`);
206
+ existing.history = (existing.history ?? []).filter((e) => e.filename !== ref);
207
+ config.definitions[guid] = existing;
208
+ await this.writeConfig(config);
209
+ }
210
+ async delete(guid) {
211
+ const config = await this.readConfig();
212
+ delete config.definitions[guid];
213
+ await this.writeConfig(config);
214
+ }
215
+ }
216
+ //# sourceMappingURL=filesystem-meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem-meta.js","sourceRoot":"","sources":["../../../src/definitions/providers/filesystem-meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Read a JSON file, returning a fallback if the file does not exist.
3
+ * Any other error propagates.
4
+ */
5
+ export declare function readJsonFile<T>(filePath: string, fallback: T): Promise<T>;
6
+ /**
7
+ * Atomically write JSON: ensure the parent directory exists, write to a
8
+ * sibling .tmp file, then rename into place. Prevents partial writes from
9
+ * corrupting the target on crash or interrupt.
10
+ */
11
+ export declare function writeJsonFile<T>(filePath: string, data: T): Promise<void>;
12
+ //# sourceMappingURL=fsJson.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsJson.d.ts","sourceRoot":"","sources":["../src/fsJson.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQ/E;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/E"}
package/dist/fsJson.js ADDED
@@ -0,0 +1,29 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ /**
4
+ * Read a JSON file, returning a fallback if the file does not exist.
5
+ * Any other error propagates.
6
+ */
7
+ export async function readJsonFile(filePath, fallback) {
8
+ try {
9
+ const raw = await fs.readFile(filePath, 'utf-8');
10
+ return JSON.parse(raw);
11
+ }
12
+ catch (err) {
13
+ if (err.code === 'ENOENT')
14
+ return fallback;
15
+ throw err;
16
+ }
17
+ }
18
+ /**
19
+ * Atomically write JSON: ensure the parent directory exists, write to a
20
+ * sibling .tmp file, then rename into place. Prevents partial writes from
21
+ * corrupting the target on crash or interrupt.
22
+ */
23
+ export async function writeJsonFile(filePath, data) {
24
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
25
+ const tmp = `${filePath}.tmp`;
26
+ await fs.writeFile(tmp, JSON.stringify(data, null, '\t'), 'utf-8');
27
+ await fs.rename(tmp, filePath);
28
+ }
29
+ //# sourceMappingURL=fsJson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsJson.js","sourceRoot":"","sources":["../src/fsJson.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,QAAgB,EAAE,QAAW;IAClE,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,QAAQ,CAAC;QACtE,MAAM,GAAG,CAAC;IACX,CAAC;AACF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAI,QAAgB,EAAE,IAAO;IAC/D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,GAAG,QAAQ,MAAM,CAAC;IAC9B,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export { LocalAuthProvider } from './auth/LocalAuthProvider.js';
2
+ export type { LocalAuthProviderConfig } from './auth/LocalAuthProvider.js';
3
+ export { signHmacToken, verifyHmacToken } from './auth/hmac.js';
4
+ export { hashPassword, verifyPasswordHash, createLocalAuthUserStore } from './auth/users.js';
5
+ export type { StoredAuthUser, AuthUsersFile, LocalAuthUserStore } from './auth/users.js';
6
+ export { LocalDataProvider, LocalOrgStore, LocalOrgStoreLoader, LocalProjectStore, LocalDefinitionStore, LocalInviteStore, LocalComputeServerStore, LocalShareLinkStore, LocalPlatformProjectGrantStore } from './data/index.js';
7
+ export type { LocalOrgStoreData, LocalOrgStoreOptions, LocalProjectStoreOptions, LocalShareLinkStoreOptions, SecretVerificationFailure, SecretVerificationFailureReason, SecretVerificationReport } from './data/index.js';
8
+ export { createLocalUserDataStore } from './data/userData.js';
9
+ export type { LocalUserDataStore, StoredUserData, UserDataFile } from './data/userData.js';
10
+ export { LocalStorageProvider } from './storage/LocalStorageProvider.js';
11
+ export { LocalUserProfileProvider } from './userProfile/LocalUserProfileProvider.js';
12
+ export { LocalPlatformPermissionStore } from './permissions/LocalPlatformPermissionStore.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC7F,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGzF,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,8BAA8B,EAC9B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACX,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,0BAA0B,EAC1B,yBAAyB,EACzB,+BAA+B,EAC/B,wBAAwB,EACxB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAG3F,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAGzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAGrF,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ // Auth — identity-only (auth-users.json)
2
+ export { LocalAuthProvider } from './auth/LocalAuthProvider.js';
3
+ export { signHmacToken, verifyHmacToken } from './auth/hmac.js';
4
+ export { hashPassword, verifyPasswordHash, createLocalAuthUserStore } from './auth/users.js';
5
+ // Data — class names use the `*Store` suffix to match the Supabase provider.
6
+ export { LocalDataProvider, LocalOrgStore, LocalOrgStoreLoader, LocalProjectStore, LocalDefinitionStore, LocalInviteStore, LocalComputeServerStore, LocalShareLinkStore, LocalPlatformProjectGrantStore } from './data/index.js';
7
+ // Per-user data layer (user-data.json) — keyed by user ID, paired with any
8
+ // auth provider. The permission and profile stores both read/write here.
9
+ export { createLocalUserDataStore } from './data/userData.js';
10
+ // Storage
11
+ export { LocalStorageProvider } from './storage/LocalStorageProvider.js';
12
+ // User profile
13
+ export { LocalUserProfileProvider } from './userProfile/LocalUserProfileProvider.js';
14
+ // Platform permissions (data-layer authorization store)
15
+ export { LocalPlatformPermissionStore } from './permissions/LocalPlatformPermissionStore.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAG7F,6EAA6E;AAC7E,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,8BAA8B,EAC9B,MAAM,iBAAiB,CAAC;AAWzB,2EAA2E;AAC3E,yEAAyE;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAG9D,UAAU;AACV,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEzE,eAAe;AACf,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAErF,wDAAwD;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,+CAA+C,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { IInviteStore, Invite, RequestContext, ListOptions, Page } from '@selva/platform';
2
+ /**
3
+ * Filesystem-backed invite store (invites.json in DATA_PATH).
4
+ *
5
+ * Notes:
6
+ * - No explicit per-call scoping by ctx.userId — the route layer gates
7
+ * admin actions (manage_users + correct org). `getByToken` is the one
8
+ * unauthenticated read and is implicitly scoped by the secret token.
9
+ * - Expired or already-accepted invites are hidden from `getByToken` so
10
+ * a reused link returns null and the public route surfaces a clean error.
11
+ */
12
+ export declare class LocalInviteProvider implements IInviteStore {
13
+ private readonly filePath;
14
+ static fromEnv(env: Record<string, string | undefined>): LocalInviteProvider;
15
+ constructor(dataPath: string);
16
+ private load;
17
+ private save;
18
+ create(_ctx: RequestContext, invite: Invite): Promise<void>;
19
+ getByToken(_ctx: RequestContext, token: string): Promise<Invite | null>;
20
+ listByOrg(_ctx: RequestContext, orgId: string, opts?: ListOptions): Promise<Page<Invite>>;
21
+ markAccepted(_ctx: RequestContext, id: string, userId: string): Promise<void>;
22
+ revoke(_ctx: RequestContext, id: string): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=LocalInviteProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LocalInviteProvider.d.ts","sourceRoot":"","sources":["../../src/invites/LocalInviteProvider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,YAAY,EACZ,MAAM,EACN,cAAc,EACd,WAAW,EACX,IAAI,EACJ,MAAM,iBAAiB,CAAC;AA+BzB;;;;;;;;;GASG;AACH,qBAAa,mBAAoB,YAAW,YAAY;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,mBAAmB;gBAKhE,QAAQ,EAAE,MAAM;YAId,IAAI;YAIJ,IAAI;IAIZ,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3D,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASvE,SAAS,CACd,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAMlB,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7E,MAAM,CAAC,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM7D"}
@@ -0,0 +1,89 @@
1
+ import * as path from 'node:path';
2
+ import { paginate, applyOrder } from '../pagination.js';
3
+ import { readJsonFile, writeJsonFile } from '../fsJson.js';
4
+ const EMPTY = { invites: [] };
5
+ /**
6
+ * Pre-§1g invite records carried a flat `permissions` array. Drop any entry
7
+ * that isn't a valid OrgPermission (including the legacy `platform_admin`,
8
+ * which is no longer invite-grantable) and store the result under
9
+ * `orgPermissions`.
10
+ */
11
+ const VALID_ORG_PERMS = new Set([
12
+ 'manage_users',
13
+ 'manage_compute',
14
+ 'manage_definitions',
15
+ 'manage_projects'
16
+ ]);
17
+ function migrateInvite(i) {
18
+ if (i.orgPermissions === undefined) {
19
+ const legacy = i.permissions ?? [];
20
+ i.orgPermissions = legacy.filter((p) => VALID_ORG_PERMS.has(p));
21
+ delete i.permissions;
22
+ }
23
+ return i;
24
+ }
25
+ /**
26
+ * Filesystem-backed invite store (invites.json in DATA_PATH).
27
+ *
28
+ * Notes:
29
+ * - No explicit per-call scoping by ctx.userId — the route layer gates
30
+ * admin actions (manage_users + correct org). `getByToken` is the one
31
+ * unauthenticated read and is implicitly scoped by the secret token.
32
+ * - Expired or already-accepted invites are hidden from `getByToken` so
33
+ * a reused link returns null and the public route surfaces a clean error.
34
+ */
35
+ export class LocalInviteProvider {
36
+ filePath;
37
+ static fromEnv(env) {
38
+ if (!env.DATA_PATH)
39
+ throw new Error('Missing required env var: DATA_PATH');
40
+ return new LocalInviteProvider(env.DATA_PATH);
41
+ }
42
+ constructor(dataPath) {
43
+ this.filePath = path.join(dataPath, 'invites.json');
44
+ }
45
+ async load() {
46
+ return readJsonFile(this.filePath, EMPTY);
47
+ }
48
+ async save(file) {
49
+ await writeJsonFile(this.filePath, file);
50
+ }
51
+ async create(_ctx, invite) {
52
+ const file = await this.load();
53
+ file.invites.push(invite);
54
+ await this.save(file);
55
+ }
56
+ async getByToken(_ctx, token) {
57
+ const { invites } = await this.load();
58
+ const invite = invites.find((i) => i.token === token);
59
+ if (!invite)
60
+ return null;
61
+ if (invite.acceptedAt)
62
+ return null;
63
+ if (Date.parse(invite.expiresAt) <= Date.now())
64
+ return null;
65
+ return migrateInvite(invite);
66
+ }
67
+ async listByOrg(_ctx, orgId, opts) {
68
+ const { invites } = await this.load();
69
+ const filtered = invites.filter((i) => i.orgId === orgId).map(migrateInvite);
70
+ return paginate(applyOrder(filtered, opts), opts);
71
+ }
72
+ async markAccepted(_ctx, id, userId) {
73
+ const file = await this.load();
74
+ const invite = file.invites.find((i) => i.id === id);
75
+ if (!invite || invite.acceptedAt)
76
+ return;
77
+ invite.acceptedAt = new Date().toISOString();
78
+ invite.acceptedByUserId = userId;
79
+ await this.save(file);
80
+ }
81
+ async revoke(_ctx, id) {
82
+ const file = await this.load();
83
+ const before = file.invites.length;
84
+ file.invites = file.invites.filter((i) => i.id !== id || i.acceptedAt);
85
+ if (file.invites.length !== before)
86
+ await this.save(file);
87
+ }
88
+ }
89
+ //# sourceMappingURL=LocalInviteProvider.js.map