cabloy 5.1.95 → 5.1.97

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 (208) hide show
  1. package/.cabloy-version +1 -0
  2. package/.claude/skills/cabloy-backend-scaffold/references/follow-up-checklist.md +4 -1
  3. package/.claude/skills/cabloy-resource-field-update/SKILL.md +6 -3
  4. package/.github/workflows/vona-test-crud.yml +2 -0
  5. package/.github/workflows/vona-test-mysql.yml +2 -0
  6. package/.github/workflows/vona-test-pg.yml +2 -0
  7. package/.github/workflows/vona-test-sqlite3.yml +2 -0
  8. package/CHANGELOG.md +38 -0
  9. package/CLAUDE.md +1 -0
  10. package/cabloy-docs/ai/playbook-backend-module.md +6 -3
  11. package/cabloy-docs/fullstack/framework-performance.md +3 -3
  12. package/cabloy-docs/fullstack/quickstart.md +1 -1
  13. package/package.json +1 -1
  14. package/scripts/release.ts +27 -1
  15. package/vona/docker-compose-original/docker-compose-dockerfile-app +4 -0
  16. package/vona/docker-compose-original/docker-compose.original.yml +0 -1
  17. package/vona/env/.env +0 -1
  18. package/vona/env/.env.prod +0 -1
  19. package/vona/env/.env.prod.docker +0 -7
  20. package/vona/package.original.json +3 -3
  21. package/vona/packages-cli/cabloy-cli/package.json +2 -2
  22. package/vona/packages-cli/cli/package.json +1 -1
  23. package/vona/packages-cli/cli-set-api/package.json +2 -2
  24. package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.build.ts +70 -2
  25. package/vona/packages-utils/babel-plugin-vona-bean-module/package.json +2 -2
  26. package/vona/packages-utils/module-glob/package.json +2 -2
  27. package/vona/packages-utils/module-info-pro/package.json +2 -2
  28. package/vona/packages-utils/utils/package.json +2 -2
  29. package/vona/packages-vona/vona/package.json +1 -1
  30. package/vona/packages-vona/vona-core/package.json +2 -2
  31. package/vona/packages-vona/vona-core/src/lib/addon/addon.ts +77 -0
  32. package/vona/packages-vona/vona-core/src/lib/addon/index.ts +3 -0
  33. package/vona/packages-vona/vona-core/src/lib/addon/sharp.ts +46 -0
  34. package/vona/packages-vona/vona-core/src/lib/addon/sqlite3.ts +23 -0
  35. package/vona/packages-vona/vona-core/src/lib/index.ts +1 -0
  36. package/vona/packages-vona/vona-core/src/lib/utils/index.ts +0 -1
  37. package/vona/packages-vona/vona-core/src/lib/utils/util.ts +5 -0
  38. package/vona/packages-vona/vona-mock/package.json +2 -2
  39. package/vona/pnpm-lock.yaml +441 -62
  40. package/vona/pnpm-workspace.yaml +1 -1
  41. package/vona/src/backend/cli.ts +2 -5
  42. package/vona/src/backend/config/config/config.ts +0 -4
  43. package/vona/src/suite/a-demo/modules/demo-basic/src/bean/ssrMenu.admin.ts +1 -1
  44. package/vona/src/suite/a-training/modules/training-record/src/.metadata/index.ts +26 -0
  45. package/vona/src/suite/a-training/modules/training-record/src/bean/imageScene.sceneImage.ts +11 -0
  46. package/vona/src/suite/a-training/modules/training-record/src/bean/meta.version.ts +1 -0
  47. package/vona/src/suite/a-training/modules/training-record/src/config/locale/en-us.ts +1 -0
  48. package/vona/src/suite/a-training/modules/training-record/src/config/locale/zh-cn.ts +1 -0
  49. package/vona/src/suite/a-training/modules/training-record/src/dto/recordSelectResItem.tsx +12 -0
  50. package/vona/src/suite/a-training/modules/training-record/src/dto/recordView.tsx +12 -0
  51. package/vona/src/suite/a-training/modules/training-record/src/entity/record.tsx +26 -1
  52. package/vona/src/suite/a-training/modules/training-record/src/index.ts +1 -0
  53. package/vona/src/suite/a-training/modules/training-student/src/.metadata/index.ts +27 -1
  54. package/vona/src/suite/a-training/modules/training-student/src/bean/imageScene.studentImage.ts +10 -0
  55. package/vona/src/suite/a-training/modules/training-student/src/bean/meta.version.ts +1 -0
  56. package/vona/src/suite/a-training/modules/training-student/src/config/locale/en-us.ts +1 -0
  57. package/vona/src/suite/a-training/modules/training-student/src/config/locale/zh-cn.ts +1 -0
  58. package/vona/src/suite/a-training/modules/training-student/src/dto/detailRecordBase.tsx +16 -2
  59. package/vona/src/suite/a-training/modules/training-student/src/dto/studentCreate.tsx +1 -1
  60. package/vona/src/suite/a-training/modules/training-student/src/dto/studentSelectResItem.tsx +12 -0
  61. package/vona/src/suite/a-training/modules/training-student/src/dto/studentUpdate.tsx +1 -1
  62. package/vona/src/suite/a-training/modules/training-student/src/dto/studentView.tsx +13 -1
  63. package/vona/src/suite/a-training/modules/training-student/src/entity/student.tsx +26 -1
  64. package/vona/src/suite/a-training/modules/training-student/src/index.ts +1 -0
  65. package/vona/src/suite/a-training/modules/training-student/src/model/student.ts +1 -0
  66. package/vona/src/suite-vendor/a-auth/modules/a-auth/package.json +1 -1
  67. package/vona/src/suite-vendor/a-auth/modules/a-auth/src/bean/bean.authProvider.ts +2 -5
  68. package/vona/src/suite-vendor/a-auth/package.json +1 -1
  69. package/vona/src/suite-vendor/a-image/modules/a-image/cli/imageProvider/boilerplate/{{sceneName}}.{{beanName}}.ts_ +23 -0
  70. package/vona/src/suite-vendor/a-image/modules/a-image/cli/imageScene/boilerplate/{{sceneName}}.{{beanName}}.ts_ +5 -0
  71. package/vona/src/suite-vendor/a-image/modules/a-image/package.json +68 -0
  72. package/vona/src/suite-vendor/a-image/modules/a-image/src/.metadata/index.ts +482 -0
  73. package/vona/src/suite-vendor/a-image/modules/a-image/src/.metadata/locales.ts +18 -0
  74. package/vona/src/suite-vendor/a-image/modules/a-image/src/.metadata/this.ts +2 -0
  75. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/bean.image.ts +443 -0
  76. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/bean.imageProvider.ts +55 -0
  77. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/bean.imageUploadPolicy.ts +174 -0
  78. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/meta.redlock.ts +11 -0
  79. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/meta.version.ts +40 -0
  80. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/serializerTransform.resolveView.ts +44 -0
  81. package/vona/src/suite-vendor/a-image/modules/a-image/src/bean/serializerTransform.resolveViews.ts +44 -0
  82. package/vona/src/suite-vendor/a-image/modules/a-image/src/config/config.ts +17 -0
  83. package/vona/src/suite-vendor/a-image/modules/a-image/src/config/locale/en-us.ts +1 -0
  84. package/vona/src/suite-vendor/a-image/modules/a-image/src/config/locale/zh-cn.ts +1 -0
  85. package/vona/src/suite-vendor/a-image/modules/a-image/src/controller/image.ts +165 -0
  86. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageDeliveryRequest.ts +20 -0
  87. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageDirectUploadRequest.ts +36 -0
  88. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageDirectUploadResponse.ts +38 -0
  89. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageTransformOptions.tsx +42 -0
  90. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadResponse.ts +62 -0
  91. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadTokenRequest.ts +24 -0
  92. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadTokenResponse.ts +16 -0
  93. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageUploadUrlRequest.ts +33 -0
  94. package/vona/src/suite-vendor/a-image/modules/a-image/src/dto/imageView.ts +46 -0
  95. package/vona/src/suite-vendor/a-image/modules/a-image/src/entity/image.ts +58 -0
  96. package/vona/src/suite-vendor/a-image/modules/a-image/src/entity/imageProvider.ts +24 -0
  97. package/vona/src/suite-vendor/a-image/modules/a-image/src/index.ts +4 -0
  98. package/vona/src/suite-vendor/a-image/modules/a-image/src/lib/imageProvider.ts +9 -0
  99. package/vona/src/suite-vendor/a-image/modules/a-image/src/lib/imageScene.ts +7 -0
  100. package/vona/src/suite-vendor/a-image/modules/a-image/src/lib/imageVariant.ts +46 -0
  101. package/vona/src/suite-vendor/a-image/modules/a-image/src/lib/index.ts +3 -0
  102. package/vona/src/suite-vendor/a-image/modules/a-image/src/model/image.ts +10 -0
  103. package/vona/src/suite-vendor/a-image/modules/a-image/src/model/imageProvider.ts +10 -0
  104. package/vona/src/suite-vendor/a-image/modules/a-image/src/types/image.ts +208 -0
  105. package/vona/src/suite-vendor/a-image/modules/a-image/src/types/imageProvider.ts +110 -0
  106. package/vona/src/suite-vendor/a-image/modules/a-image/src/types/imageScene.ts +52 -0
  107. package/vona/src/suite-vendor/a-image/modules/a-image/src/types/index.ts +3 -0
  108. package/vona/src/suite-vendor/a-image/modules/a-image/tsconfig.build.json +11 -0
  109. package/vona/src/suite-vendor/a-image/modules/a-image/tsconfig.json +7 -0
  110. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/package.json +49 -0
  111. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/.metadata/index.ts +89 -0
  112. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/.metadata/this.ts +2 -0
  113. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/bean/imageProvider.cloudflare.ts +155 -0
  114. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/index.ts +1 -0
  115. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/lib/cloudflareImageUrl.ts +112 -0
  116. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/src/service/imageCloudflare.ts +273 -0
  117. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/tsconfig.build.json +11 -0
  118. package/vona/src/suite-vendor/a-image/modules/image-cloudflare/tsconfig.json +7 -0
  119. package/vona/src/suite-vendor/a-image/modules/image-native/package.json +63 -0
  120. package/vona/src/suite-vendor/a-image/modules/image-native/src/.metadata/index.ts +114 -0
  121. package/vona/src/suite-vendor/a-image/modules/image-native/src/.metadata/this.ts +2 -0
  122. package/vona/src/suite-vendor/a-image/modules/image-native/src/bean/imageProvider.native.ts +131 -0
  123. package/vona/src/suite-vendor/a-image/modules/image-native/src/config/config.ts +11 -0
  124. package/vona/src/suite-vendor/a-image/modules/image-native/src/index.ts +1 -0
  125. package/vona/src/suite-vendor/a-image/modules/image-native/src/monkey.ts +33 -0
  126. package/vona/src/suite-vendor/a-image/modules/image-native/src/service/imageNative.ts +291 -0
  127. package/vona/src/suite-vendor/a-image/modules/image-native/tsconfig.build.json +11 -0
  128. package/vona/src/suite-vendor/a-image/modules/image-native/tsconfig.json +7 -0
  129. package/vona/src/suite-vendor/a-image/package.json +14 -0
  130. package/vona/src/suite-vendor/a-image/tsconfig.base.json +4 -0
  131. package/vona/src/suite-vendor/a-image/tsconfig.json +16 -0
  132. package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +2 -2
  133. package/vona/src/suite-vendor/a-vona/modules/a-jwt/package.json +1 -1
  134. package/vona/src/suite-vendor/a-vona/modules/a-jwt/src/service/jwtClient.ts +5 -0
  135. package/vona/src/suite-vendor/a-vona/modules/a-jwt/src/types/jwt.ts +1 -0
  136. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/package.json +1 -1
  137. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/lib/schema/makeSchemaLikes.ts +6 -3
  138. package/vona/src/suite-vendor/a-vona/modules/a-openapiutils/src/lib/utils.ts +13 -7
  139. package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
  140. package/vona/src/suite-vendor/a-vona/modules/a-orm/src/types/database.ts +0 -1
  141. package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +9 -1
  142. package/vona/src/suite-vendor/a-vona/modules/a-upload/package.json +1 -1
  143. package/vona/src/suite-vendor/a-vona/modules/a-upload/src/bean/interceptor.upload.ts +39 -7
  144. package/vona/src/suite-vendor/a-vona/package.json +1 -1
  145. package/zova/packages-cli/cli/package.json +3 -3
  146. package/zova/packages-cli/cli-set-front/package.json +9 -9
  147. package/zova/packages-cli/cli-set-front/src/lib/bean/cli.openapi.generate.ts +20 -10
  148. package/zova/packages-utils/babel-plugin-zova-bean-module/package.json +2 -2
  149. package/zova/packages-utils/babel-plugin-zova-bean-use/package.json +2 -2
  150. package/zova/packages-utils/babel-plugin-zova-behavior/package.json +2 -2
  151. package/zova/packages-utils/babel-plugin-zova-component/package.json +2 -2
  152. package/zova/packages-utils/zova-jsx/package.json +3 -3
  153. package/zova/packages-utils/zova-vite/package.json +7 -7
  154. package/zova/packages-zova/zova/package.json +3 -3
  155. package/zova/packages-zova/zova-core/package.json +3 -3
  156. package/zova/pnpm-lock.yaml +126 -74
  157. package/zova/src/suite/a-home/modules/home-api/src/api/captcha.ts +3 -1
  158. package/zova/src/suite/a-home/modules/home-api/src/api/home.ts +3 -1
  159. package/zova/src/suite/a-home/modules/home-api/src/api/homeBaseMenu.ts +3 -1
  160. package/zova/src/suite/a-home/modules/home-api/src/api/homeBasePermission.ts +3 -1
  161. package/zova/src/suite/a-home/modules/home-api/src/api/homeUserPassport.ts +22 -20
  162. package/zova/src/suite/a-home/modules/home-api/src/api/openapi/schemas.ts +163 -53
  163. package/zova/src/suite/a-home/modules/home-api/src/api/openapi/types.ts +2060 -675
  164. package/zova/src/suite/a-home/modules/home-api/src/api/testSsrToolOne.ts +3 -1
  165. package/zova/src/suite/a-home/modules/home-api/src/apiSchema/captcha.ts +3 -1
  166. package/zova/src/suite/a-home/modules/home-api/src/apiSchema/home.ts +3 -1
  167. package/zova/src/suite/a-home/modules/home-api/src/apiSchema/homeBaseMenu.ts +3 -1
  168. package/zova/src/suite/a-home/modules/home-api/src/apiSchema/homeBasePermission.ts +3 -1
  169. package/zova/src/suite/a-home/modules/home-api/src/apiSchema/homeUserPassport.ts +13 -11
  170. package/zova/src/suite/a-home/modules/home-api/src/apiSchema/testSsrToolOne.ts +3 -1
  171. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/schemas.ts +54 -16
  172. package/zova/src/suite/a-training/modules/training-student/src/api/openapi/types.ts +468 -8
  173. package/zova/src/suite/a-training/modules/training-student/src/apiSchema/trainingStudent.ts +3 -1
  174. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionUpdate.tsx +1 -1
  175. package/zova/src/suite/cabloy-basic/modules/basic-details/src/component/actionCreate/controller.tsx +1 -1
  176. package/zova/src/suite/cabloy-basic/modules/basic-details/src/service/detail.tsx +53 -1
  177. package/zova/src/suite/cabloy-basic/modules/basic-image/cli/openapi.config.ts +9 -0
  178. package/zova/src/suite/cabloy-basic/modules/basic-image/package.json +60 -0
  179. package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/component/formFieldImage.ts +31 -0
  180. package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/index.ts +191 -0
  181. package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/locales.ts +7 -0
  182. package/zova/src/suite/cabloy-basic/modules/basic-image/src/.metadata/this.ts +2 -0
  183. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/image.ts +104 -0
  184. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/baseURL.ts +5 -0
  185. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/index.ts +3 -0
  186. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/schemas.ts +262 -0
  187. package/zova/src/suite/cabloy-basic/modules/basic-image/src/api/openapi/types.ts +5159 -0
  188. package/zova/src/suite/cabloy-basic/modules/basic-image/src/apiSchema/image.ts +35 -0
  189. package/zova/src/suite/cabloy-basic/modules/basic-image/src/bean/tableCell.image.tsx +200 -0
  190. package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/formFieldImage/controller.tsx +781 -0
  191. package/zova/src/suite/cabloy-basic/modules/basic-image/src/config/locale/en-us.ts +18 -0
  192. package/zova/src/suite/cabloy-basic/modules/basic-image/src/config/locale/zh-cn.ts +18 -0
  193. package/zova/src/suite/cabloy-basic/modules/basic-image/src/index.ts +4 -0
  194. package/zova/src/suite/cabloy-basic/modules/basic-image/src/lib/index.ts +2 -0
  195. package/zova/src/suite/cabloy-basic/modules/basic-image/src/lib/preview.ts +105 -0
  196. package/zova/src/suite/cabloy-basic/modules/basic-image/src/lib/previewDialog.tsx +190 -0
  197. package/zova/src/suite/cabloy-basic/modules/basic-image/src/types/image.ts +5 -0
  198. package/zova/src/suite/cabloy-basic/modules/basic-image/src/types/index.ts +1 -0
  199. package/zova/src/suite/cabloy-basic/modules/basic-image/tsconfig.build.json +13 -0
  200. package/zova/src/suite/cabloy-basic/modules/basic-image/tsconfig.json +5 -0
  201. package/zova/src/suite/cabloy-basic/package.json +1 -0
  202. package/zova/src/suite-vendor/a-zova/modules/a-openapi/package.json +1 -1
  203. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/image.ts +1 -0
  204. package/zova/src/suite-vendor/a-zova/modules/a-openapi/src/types/index.ts +1 -0
  205. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +5 -5
  206. package/zova/src/suite-vendor/a-zova/package.json +3 -3
  207. package/vona/packages-vona/vona-core/src/lib/utils/sqlite3.ts +0 -50
  208. /package/vona/patches/{zova-core@5.1.75.patch → zova-core@5.1.76.patch} +0 -0
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "vona-module-image-native",
3
+ "version": "5.0.1",
4
+ "description": "",
5
+ "keywords": [
6
+ "Vona Module"
7
+ ],
8
+ "author": "",
9
+ "files": [
10
+ "dist",
11
+ "src"
12
+ ],
13
+ "type": "module",
14
+ "exports": {
15
+ ".": {
16
+ "types": [
17
+ "./src/index.ts",
18
+ "./dist/index.d.ts"
19
+ ],
20
+ "import": "./src/index.ts",
21
+ "default": "./dist/index.js"
22
+ },
23
+ "./package.json": "./package.json"
24
+ },
25
+ "scripts": {
26
+ "clean": "rimraf dist tsconfig.build.tsbuildinfo",
27
+ "tsc:publish": "npm run clean && node ../../../../../packages-cli/cli/src/bin/vona.ts :bin:buildModule --sourcemap && tsc -p tsconfig.build.json",
28
+ "prepublishOnly": "npm run tsc:publish",
29
+ "prepack": "clean-package",
30
+ "postpack": "clean-package restore"
31
+ },
32
+ "dependencies": {
33
+ "sharp": "^0.35.2"
34
+ },
35
+ "devDependencies": {
36
+ "clean-package": "^2.2.0",
37
+ "rimraf": "^6.1.3"
38
+ },
39
+ "clean-package": {
40
+ "indent": 2,
41
+ "remove": [
42
+ "clean-package",
43
+ "exports.\\..import"
44
+ ]
45
+ },
46
+ "title": "image-native",
47
+ "vonaModule": {
48
+ "dependencies": {
49
+ "a-image": "5.0.0"
50
+ },
51
+ "globalDependencies": {
52
+ "sharp": true
53
+ },
54
+ "bundle": {
55
+ "externals": [
56
+ "sharp"
57
+ ]
58
+ },
59
+ "capabilities": {
60
+ "monkey": true
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,114 @@
1
+ // eslint-disable
2
+ /** service: begin */
3
+ export * from '../service/imageNative.ts';
4
+
5
+ import 'vona-module-a-bean';
6
+ declare module 'vona-module-a-bean' {
7
+
8
+ export interface IServiceRecord {
9
+ 'image-native:imageNative': never;
10
+ }
11
+
12
+
13
+ }
14
+ declare module 'vona-module-image-native' {
15
+
16
+ export interface ServiceImageNative {
17
+ /** @internal */
18
+ get scope(): ScopeModuleImageNative;
19
+ }
20
+
21
+ export interface ServiceImageNative {
22
+ get $beanFullName(): 'image-native.service.imageNative';
23
+ get $onionName(): 'image-native:imageNative';
24
+
25
+ }
26
+ }
27
+ /** service: end */
28
+ /** service: begin */
29
+ import type { ServiceImageNative } from '../service/imageNative.ts';
30
+ export interface IModuleService {
31
+ 'imageNative': ServiceImageNative;
32
+ }
33
+ /** service: end */
34
+ /** service: begin */
35
+
36
+ import 'vona';
37
+ declare module 'vona' {
38
+ export interface IBeanRecordGeneral {
39
+ 'image-native.service.imageNative': ServiceImageNative;
40
+ }
41
+ }
42
+ /** service: end */
43
+ /** imageProvider: begin */
44
+ export * from '../bean/imageProvider.native.ts';
45
+ import type { IImageProviderOptionsNative } from '../bean/imageProvider.native.ts';
46
+ import 'vona-module-a-image';
47
+ declare module 'vona-module-a-image' {
48
+
49
+ export interface IImageProviderRecord {
50
+ 'image-native:native': IImageProviderOptionsNative;
51
+ }
52
+
53
+
54
+ }
55
+ declare module 'vona-module-image-native' {
56
+
57
+ export interface ImageProviderNative {
58
+ /** @internal */
59
+ get scope(): ScopeModuleImageNative;
60
+ }
61
+
62
+ export interface ImageProviderNative {
63
+ get $beanFullName(): 'image-native.imageProvider.native';
64
+ get $onionName(): 'image-native:native';
65
+ get $onionOptions(): IImageProviderOptionsNative;
66
+ }
67
+ }
68
+ /** imageProvider: end */
69
+ /** imageProvider: begin */
70
+ import type { ImageProviderNative } from '../bean/imageProvider.native.ts';
71
+ export interface IModuleImageProvider {
72
+ 'native': ImageProviderNative;
73
+ }
74
+ /** imageProvider: end */
75
+ /** config: begin */
76
+ export * from '../config/config.ts';
77
+ import type { config } from '../config/config.ts';
78
+ /** config: end */
79
+ /** monkey: begin */
80
+ export * from '../monkey.ts';
81
+ /** monkey: end */
82
+ /** scope: begin */
83
+ import { BeanScopeBase, type BeanScopeUtil, type TypeModuleConfig } from 'vona';
84
+ import { Scope } from 'vona-module-a-bean';
85
+
86
+ @Scope()
87
+ export class ScopeModuleImageNative extends BeanScopeBase {}
88
+
89
+ export interface ScopeModuleImageNative {
90
+ util: BeanScopeUtil;
91
+ config: TypeModuleConfig<typeof config>;
92
+ service: IModuleService;
93
+ imageProvider: IModuleImageProvider;
94
+ }
95
+
96
+ import 'vona';
97
+ declare module 'vona' {
98
+ export interface IBeanScopeRecord {
99
+ 'image-native': ScopeModuleImageNative;
100
+ }
101
+
102
+ export interface IBeanScopeContainer {
103
+ imageNative: ScopeModuleImageNative;
104
+ }
105
+
106
+ export interface IBeanScopeConfig {
107
+ 'image-native': ReturnType<typeof config>;
108
+ }
109
+
110
+
111
+
112
+
113
+ }
114
+ /** scope: end */
@@ -0,0 +1,2 @@
1
+ export const __ThisModule__ = 'image-native';
2
+ export { ScopeModuleImageNative as ScopeModule } from './index.ts';
@@ -0,0 +1,131 @@
1
+ import type {
2
+ IDecoratorImageProviderOptions,
3
+ IImageDeliveryOptions,
4
+ IImageDownloadResult,
5
+ IImageProviderClientOptions,
6
+ IImageProviderClientRecord,
7
+ IImageProviderExecute,
8
+ IImageProviderResource,
9
+ IImageUploadInput,
10
+ IImageVariantRequest,
11
+ } from 'vona-module-a-image';
12
+ import type { EntityImage } from 'vona-module-a-image';
13
+
14
+ import fse from 'fs-extra';
15
+ import { BeanBase } from 'vona';
16
+ import { ImageProvider } from 'vona-module-a-image';
17
+
18
+ export interface IImageProviderNativeClientRecord extends IImageProviderClientRecord {}
19
+
20
+ export interface IImageProviderNativeClientOptions extends IImageProviderClientOptions {
21
+ subdir?: string;
22
+ signingKey?: string;
23
+ tokenName?: string;
24
+ }
25
+
26
+ export interface IImageProviderOptionsNative extends IDecoratorImageProviderOptions<
27
+ IImageProviderNativeClientRecord,
28
+ IImageProviderNativeClientOptions
29
+ > {}
30
+
31
+ @ImageProvider<IImageProviderOptionsNative>({
32
+ base: {
33
+ subdir: 'default',
34
+ signedDeliveryKind: 'proxy',
35
+ },
36
+ })
37
+ export class ImageProviderNative extends BeanBase implements IImageProviderExecute {
38
+ async upload(
39
+ input: IImageUploadInput,
40
+ clientOptions: IImageProviderNativeClientOptions,
41
+ _options: IImageProviderOptionsNative,
42
+ ): Promise<IImageProviderResource> {
43
+ const resource = await this.scope.service.imageNative.upload(input, clientOptions);
44
+ return {
45
+ ...resource,
46
+ filename: input.filename,
47
+ contentType: input.contentType,
48
+ meta: input.meta,
49
+ };
50
+ }
51
+
52
+ async get(
53
+ image: EntityImage,
54
+ clientOptions: IImageProviderNativeClientOptions,
55
+ _options: IImageProviderOptionsNative,
56
+ ) {
57
+ return {
58
+ resourceId: image.resourceId,
59
+ filename: image.filename,
60
+ contentType: image.contentType,
61
+ size: image.size,
62
+ width: image.width,
63
+ height: image.height,
64
+ requireSignedURLs: image.requireSignedURLs,
65
+ variants: image.variants,
66
+ meta: image.meta,
67
+ storagePath: image.storagePath,
68
+ deliveryBaseUrl: image.deliveryBaseUrl ?? clientOptions.deliveryBaseUrl,
69
+ };
70
+ }
71
+
72
+ async delete(
73
+ image: EntityImage,
74
+ _clientOptions: IImageProviderClientOptions,
75
+ _options: IImageProviderOptionsNative,
76
+ ) {
77
+ await this.scope.service.imageNative.remove(image);
78
+ }
79
+
80
+ async getVariantUrl(
81
+ image: EntityImage,
82
+ request: IImageVariantRequest,
83
+ clientOptions: IImageProviderNativeClientOptions,
84
+ _options: IImageProviderOptionsNative,
85
+ deliveryOptions?: IImageDeliveryOptions,
86
+ ) {
87
+ return await this.scope.service.imageNative.getVariantUrl(
88
+ image,
89
+ request,
90
+ {
91
+ ...clientOptions,
92
+ subdir: clientOptions.subdir ?? 'default',
93
+ deliveryBaseUrl: image.deliveryBaseUrl ?? clientOptions.deliveryBaseUrl,
94
+ },
95
+ deliveryOptions,
96
+ );
97
+ }
98
+
99
+ async download(
100
+ image: EntityImage,
101
+ request: IImageVariantRequest,
102
+ clientOptions: IImageProviderNativeClientOptions,
103
+ options: IImageProviderOptionsNative,
104
+ deliveryOptions?: IImageDeliveryOptions,
105
+ ): Promise<IImageDownloadResult> {
106
+ if (
107
+ (deliveryOptions?.responseMode ?? 'auto') !== 'url' &&
108
+ !deliveryOptions?.signed &&
109
+ request.variantName === 'original' &&
110
+ !request.transformOptions
111
+ ) {
112
+ const buffer = image.storagePath ? await fse.readFile(image.storagePath) : undefined;
113
+ if (buffer) {
114
+ return {
115
+ kind: 'buffer',
116
+ buffer,
117
+ filename: image.filename,
118
+ contentType: image.contentType,
119
+ signed: false,
120
+ };
121
+ }
122
+ }
123
+ return {
124
+ kind: 'url',
125
+ url: await this.getVariantUrl(image, request, clientOptions, options, deliveryOptions),
126
+ filename: image.filename,
127
+ contentType: image.contentType,
128
+ signed: !!deliveryOptions?.signed,
129
+ };
130
+ }
131
+ }
@@ -0,0 +1,11 @@
1
+ import type { VonaApplication } from 'vona';
2
+
3
+ export function config(_app: VonaApplication) {
4
+ return {
5
+ imageNative: {
6
+ variants: {
7
+ original: {},
8
+ },
9
+ },
10
+ };
11
+ }
@@ -0,0 +1 @@
1
+ export * from './.metadata/index.ts';
@@ -0,0 +1,33 @@
1
+ import type { IMonkeyAppStart } from 'vona';
2
+
3
+ import fse from 'fs-extra';
4
+ import path from 'node:path';
5
+ import { BeanSimple, cast, getPlatformArch, resolveAddon } from 'vona';
6
+
7
+ const __Version = '8.18.3';
8
+
9
+ const __MapTargetNames = {
10
+ 'linux-arm64': `libvips-cpp.so.${__Version}`,
11
+ 'linux-x64': `libvips-cpp.so.${__Version}`,
12
+ 'darwin-arm64': `libvips-cpp.${__Version}.dylib`,
13
+ 'darwin-x64': `libvips-cpp.${__Version}.dylib`,
14
+ 'win32-x64': 'libvips-42.dll',
15
+ };
16
+
17
+ export class Monkey extends BeanSimple implements IMonkeyAppStart {
18
+ async appStart() {
19
+ cast(this.app).__prepareSharpLibvips = () => {
20
+ const platformArch = getPlatformArch();
21
+ const addonFileSrc = resolveAddon('sharpLibvips');
22
+ const addonDirDest = path.join(
23
+ import.meta.dirname,
24
+ `node_modules/@img/sharp-libvips-${platformArch}/lib`,
25
+ );
26
+ const addonFileDest = path.join(addonDirDest, __MapTargetNames[platformArch]);
27
+ if (!fse.existsSync(addonFileDest)) {
28
+ fse.ensureDirSync(addonDirDest);
29
+ fse.copyFileSync(addonFileSrc, addonFileDest);
30
+ }
31
+ };
32
+ }
33
+ }
@@ -0,0 +1,291 @@
1
+ import type { SharpConstructor } from 'sharp';
2
+ import type {
3
+ EntityImage,
4
+ IImageDeliveryOptions,
5
+ IImageNamedVariants,
6
+ IImageProviderResolvedVariant,
7
+ IImageProviderResource,
8
+ IImageTransformOptions,
9
+ IImageUploadInput,
10
+ IImageVariantRequest,
11
+ } from 'vona-module-a-image';
12
+
13
+ import fse from 'fs-extra';
14
+ import { createHash } from 'node:crypto';
15
+ import path from 'node:path';
16
+ import { BeanBase, uuidv4 } from 'vona';
17
+ import { Service } from 'vona-module-a-bean';
18
+ import { resolveImageVariantRequestToTransform } from 'vona-module-a-image';
19
+
20
+ import type { IImageProviderNativeClientOptions } from '../bean/imageProvider.native.ts';
21
+
22
+ type IImageNativeStoredImage = Pick<
23
+ EntityImage,
24
+ 'resourceId' | 'filename' | 'storagePath' | 'variants'
25
+ >;
26
+
27
+ @Service()
28
+ export class ServiceImageNative extends BeanBase {
29
+ private _sharpInstance: SharpConstructor;
30
+
31
+ private async getSharp() {
32
+ if (!this._sharpInstance) {
33
+ this._sharpInstance = (await import('sharp')).default;
34
+ }
35
+ return this._sharpInstance;
36
+ }
37
+
38
+ async upload(
39
+ input: IImageUploadInput,
40
+ options: IImageProviderNativeClientOptions,
41
+ ): Promise<IImageProviderResource> {
42
+ const publicPath = await this.app.util.getPublicPathPhysical(
43
+ path.join('image-native', options.subdir ?? 'default'),
44
+ true,
45
+ );
46
+ const resourceId = uuidv4();
47
+ const ext = this._getOriginalExt(input.filename, input.file);
48
+ const targetName = `${resourceId}${ext}`;
49
+ const targetPath = path.join(publicPath, targetName);
50
+ await fse.copy(input.file, targetPath);
51
+ const sharp = await this.getSharp();
52
+ const metadata = await sharp(targetPath).metadata();
53
+ const stat = await fse.stat(targetPath);
54
+ const variants = options.variants ?? this.scope.config.imageNative.variants;
55
+ await this._generateNamedVariants(
56
+ { resourceId, filename: input.filename, storagePath: targetPath, variants },
57
+ options,
58
+ );
59
+ return {
60
+ resourceId,
61
+ size: Number(stat.size),
62
+ width: metadata.width,
63
+ height: metadata.height,
64
+ storagePath: targetPath,
65
+ deliveryBaseUrl: options.deliveryBaseUrl,
66
+ requireSignedURLs: input.requireSignedURLs ?? options.requireSignedURLs,
67
+ variants,
68
+ };
69
+ }
70
+
71
+ async remove(image: IImageNativeStoredImage) {
72
+ if (!image.storagePath) return;
73
+ const dir = path.dirname(image.storagePath);
74
+ if (!(await fse.pathExists(dir))) return;
75
+ const entries = await fse.readdir(dir);
76
+ await Promise.all(
77
+ entries
78
+ .filter(
79
+ name =>
80
+ name === path.basename(image.storagePath!) || name.startsWith(`${image.resourceId}__`),
81
+ )
82
+ .map(name => fse.remove(path.join(dir, name))),
83
+ );
84
+ }
85
+
86
+ async getVariantUrl(
87
+ image: IImageNativeStoredImage,
88
+ request: IImageVariantRequest,
89
+ options: IImageProviderNativeClientOptions,
90
+ _deliveryOptions?: IImageDeliveryOptions,
91
+ ) {
92
+ const resolved = resolveImageVariantRequestToTransform(request, 'original', image.variants);
93
+ if (
94
+ resolved.variantName === 'original' &&
95
+ this._isOriginalTransform(resolved.transformOptions)
96
+ ) {
97
+ return await this._getOriginalUrl(image, options);
98
+ }
99
+ const targetPath = await this._ensureVariantFile(image, resolved);
100
+ return await this._buildUrl(targetPath, options.deliveryBaseUrl);
101
+ }
102
+
103
+ private async _generateNamedVariants(
104
+ image: IImageNativeStoredImage,
105
+ options: IImageProviderNativeClientOptions,
106
+ ) {
107
+ const variantNames = Object.keys(image.variants ?? {}) as Array<
108
+ keyof NonNullable<IImageNamedVariants>
109
+ >;
110
+ for (const variantName of variantNames) {
111
+ if (variantName === 'original') continue;
112
+ await this._ensureVariantFile(
113
+ image,
114
+ resolveImageVariantRequestToTransform({ variantName }, 'original', image.variants),
115
+ );
116
+ }
117
+ if (!image.variants?.original) return;
118
+ await this.getVariantUrl(image, { variantName: 'original' }, options);
119
+ }
120
+
121
+ private async _ensureVariantFile(
122
+ image: IImageNativeStoredImage,
123
+ resolved: IImageProviderResolvedVariant,
124
+ ) {
125
+ if (!image.storagePath) {
126
+ throw new Error(`Image storage path missing: ${image.resourceId}`);
127
+ }
128
+ const targetPath = await this._getVariantAbsolutePath(image, resolved);
129
+ if (!(await fse.pathExists(targetPath))) {
130
+ await this._writeTransformedFile(image.storagePath, targetPath, resolved.transformOptions);
131
+ }
132
+ return targetPath;
133
+ }
134
+
135
+ private async _writeTransformedFile(
136
+ sourcePath: string,
137
+ targetPath: string,
138
+ transformOptions: IImageTransformOptions,
139
+ ) {
140
+ await fse.ensureDir(path.dirname(targetPath));
141
+ if (this._isOriginalTransform(transformOptions)) {
142
+ await fse.copy(sourcePath, targetPath, { overwrite: true });
143
+ return;
144
+ }
145
+ const sharp = await this.getSharp();
146
+ let pipeline = sharp(sourcePath, { failOn: 'none' });
147
+ const width =
148
+ transformOptions.width && transformOptions.dpr
149
+ ? Math.round(transformOptions.width * transformOptions.dpr)
150
+ : transformOptions.width;
151
+ const height =
152
+ transformOptions.height && transformOptions.dpr
153
+ ? Math.round(transformOptions.height * transformOptions.dpr)
154
+ : transformOptions.height;
155
+ if (
156
+ width ||
157
+ height ||
158
+ transformOptions.fit ||
159
+ transformOptions.gravity ||
160
+ transformOptions.background
161
+ ) {
162
+ pipeline = pipeline.resize({
163
+ width,
164
+ height,
165
+ fit: this._mapFit(transformOptions.fit),
166
+ position: this._mapGravity(transformOptions.gravity),
167
+ background: transformOptions.background,
168
+ });
169
+ }
170
+ if (transformOptions.rotate !== undefined) {
171
+ pipeline = pipeline.rotate(transformOptions.rotate);
172
+ }
173
+ if (transformOptions.sharpen !== undefined) {
174
+ pipeline = pipeline.sharpen({ sigma: transformOptions.sharpen });
175
+ }
176
+ const format = this._normalizeFormat(transformOptions.format);
177
+ if (format === 'jpeg') {
178
+ pipeline = pipeline.jpeg({ quality: transformOptions.quality });
179
+ } else if (format === 'png') {
180
+ pipeline = pipeline.png({ quality: transformOptions.quality });
181
+ } else if (format === 'webp') {
182
+ pipeline = pipeline.webp({ quality: transformOptions.quality });
183
+ } else if (format === 'avif') {
184
+ pipeline = pipeline.avif({ quality: transformOptions.quality });
185
+ }
186
+ await pipeline.toFile(targetPath);
187
+ }
188
+
189
+ private async _getOriginalUrl(
190
+ image: IImageNativeStoredImage,
191
+ options: IImageProviderNativeClientOptions,
192
+ ) {
193
+ if (!image.storagePath) {
194
+ throw new Error(`Image storage path missing: ${image.resourceId}`);
195
+ }
196
+ return await this._buildUrl(image.storagePath, options.deliveryBaseUrl);
197
+ }
198
+
199
+ private async _buildUrl(targetPath: string, deliveryBaseUrl?: string) {
200
+ const variantPath = await this._getVariantStaticPath(targetPath);
201
+ if (deliveryBaseUrl) {
202
+ return `${deliveryBaseUrl.replace(/\/$/, '')}/${variantPath}`;
203
+ }
204
+ return this.app.util.combineStaticPath(`/${variantPath}`);
205
+ }
206
+
207
+ private async _getVariantStaticPath(targetPath: string) {
208
+ const publicRoot = await this.app.util.getPublicPathPhysical(undefined, true);
209
+ const relativePath = path.relative(publicRoot, targetPath).split(path.sep).join(path.posix.sep);
210
+ return path.posix.join('public', this.ctx.instance.id.toString(), relativePath);
211
+ }
212
+
213
+ private async _getVariantAbsolutePath(
214
+ image: IImageNativeStoredImage,
215
+ resolved: IImageProviderResolvedVariant,
216
+ ) {
217
+ if (!image.storagePath) throw new Error(`Image storage path missing: ${image.resourceId}`);
218
+ const dir = path.dirname(image.storagePath);
219
+ const ext = this._getVariantExt(image.filename, image.storagePath, resolved.transformOptions);
220
+ if (resolved.variantName !== 'custom') {
221
+ const variantName = this._sanitizeVariantName(resolved.variantName);
222
+ return path.join(dir, `${image.resourceId}__${variantName}${ext}`);
223
+ }
224
+ const cacheKey = this._buildTransformCacheKey(resolved.transformOptions);
225
+ return path.join(dir, `${image.resourceId}__t_${cacheKey}${ext}`);
226
+ }
227
+
228
+ private _getVariantExt(
229
+ filename: string | undefined,
230
+ storagePath: string | undefined,
231
+ transformOptions: IImageTransformOptions,
232
+ ) {
233
+ const format = this._normalizeFormat(transformOptions.format);
234
+ if (format) {
235
+ return format === 'jpeg' ? '.jpg' : `.${format}`;
236
+ }
237
+ return path.extname(filename ?? '') || path.extname(storagePath ?? '') || '.bin';
238
+ }
239
+
240
+ private _getOriginalExt(filename: string | undefined, filePath: string) {
241
+ return path.extname(filename ?? '') || path.extname(filePath) || '.bin';
242
+ }
243
+
244
+ private _normalizeFormat(format: IImageTransformOptions['format']) {
245
+ if (!format || format === 'auto') return undefined;
246
+ return format === 'jpeg' ? 'jpeg' : format;
247
+ }
248
+
249
+ private _buildTransformCacheKey(transformOptions: IImageTransformOptions) {
250
+ const stable = this._stableStringify(transformOptions);
251
+ return createHash('sha1').update(stable).digest('hex').slice(0, 12);
252
+ }
253
+
254
+ private _stableStringify(value: unknown): string {
255
+ if (Array.isArray(value)) {
256
+ return `[${value.map(item => this._stableStringify(item)).join(',')}]`;
257
+ }
258
+ if (value && typeof value === 'object') {
259
+ const entries = Object.entries(value as Record<string, unknown>).sort(([a], [b]) =>
260
+ a.localeCompare(b),
261
+ );
262
+ return `{${entries
263
+ .map(([key, item]) => `${JSON.stringify(key)}:${this._stableStringify(item)}`)
264
+ .join(',')}}`;
265
+ }
266
+ return JSON.stringify(value);
267
+ }
268
+
269
+ private _sanitizeVariantName(variantName: string) {
270
+ return variantName.replace(/[^\w.-]/g, '-');
271
+ }
272
+
273
+ private _isOriginalTransform(transformOptions: IImageTransformOptions) {
274
+ return Object.keys(transformOptions).length === 0;
275
+ }
276
+
277
+ private _mapFit(fit: IImageTransformOptions['fit']) {
278
+ if (fit === 'scale-down') return 'inside' as const;
279
+ if (fit === 'contain' || fit === 'pad') return 'contain' as const;
280
+ if (fit === 'cover' || fit === 'crop') return 'cover' as const;
281
+ return undefined;
282
+ }
283
+
284
+ private _mapGravity(gravity: IImageTransformOptions['gravity']) {
285
+ if (gravity === 'top') return 'north';
286
+ if (gravity === 'bottom') return 'south';
287
+ if (gravity === 'left') return 'west';
288
+ if (gravity === 'right') return 'east';
289
+ return 'centre';
290
+ }
291
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.base",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "emitDeclarationOnly": true,
8
+ "outDir": "dist"
9
+ },
10
+ "include": ["src", "src/.metadata/*.ts", "src/**/*.json"]
11
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "../../tsconfig.base",
3
+ "compilerOptions": {
4
+ "noEmit": true
5
+ },
6
+ "include": ["src", "src/.metadata/*.ts", "src/**/*.json", "test"]
7
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "vona-suite-a-image",
3
+ "version": "5.0.1",
4
+ "description": "",
5
+ "author": "",
6
+ "files": [],
7
+ "type": "module",
8
+ "dependencies": {
9
+ "vona-module-a-image": "workspace:^",
10
+ "vona-module-image-cloudflare": "workspace:^",
11
+ "vona-module-image-native": "workspace:^"
12
+ },
13
+ "title": "a-image"
14
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../../../tsconfig.base",
3
+ "compilerOptions": {}
4
+ }