@nodaro/shared 1.4.2

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 (665) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +32 -0
  3. package/dist/index.cjs +12506 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +12269 -0
  6. package/dist/index.d.ts +12269 -0
  7. package/dist/index.js +11831 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +54 -0
  10. package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
  11. package/src/__tests__/ai-avatar-pricing.test.ts +321 -0
  12. package/src/__tests__/apply-video-negative-prompt.test.ts +76 -0
  13. package/src/__tests__/attach-columns.test.ts +28 -0
  14. package/src/__tests__/audio-crossfade-curves.test.ts +33 -0
  15. package/src/__tests__/build-model-menu.test.ts +58 -0
  16. package/src/__tests__/character-aspect-defaults.test.ts +142 -0
  17. package/src/__tests__/character-mention-slug.test.ts +199 -0
  18. package/src/__tests__/character-reference-photo-kinds.test.ts +32 -0
  19. package/src/__tests__/character-usage-mode.test.ts +147 -0
  20. package/src/__tests__/character-variant-assets.test.ts +142 -0
  21. package/src/__tests__/character-voice.test.ts +130 -0
  22. package/src/__tests__/cinematic-avatar-pricing.test.ts +119 -0
  23. package/src/__tests__/combine-transitions.test.ts +137 -0
  24. package/src/__tests__/component-types.test.ts +87 -0
  25. package/src/__tests__/condition-variables.test.ts +98 -0
  26. package/src/__tests__/credit-identifiers.test.ts +811 -0
  27. package/src/__tests__/default-video-provider.test.ts +63 -0
  28. package/src/__tests__/entity-image-handle.test.ts +43 -0
  29. package/src/__tests__/entity-variants.test.ts +33 -0
  30. package/src/__tests__/fal-lip-sync-sets.test.ts +31 -0
  31. package/src/__tests__/featured-entities.test.ts +33 -0
  32. package/src/__tests__/film-pricing.test.ts +64 -0
  33. package/src/__tests__/filter-condition.test.ts +285 -0
  34. package/src/__tests__/freecut-protocol.test.ts +35 -0
  35. package/src/__tests__/generate-text-items.test.ts +19 -0
  36. package/src/__tests__/generated-results.test.ts +50 -0
  37. package/src/__tests__/graph-utils.test.ts +618 -0
  38. package/src/__tests__/group-aggregation.test.ts +83 -0
  39. package/src/__tests__/i18n-locale-completeness.test.ts +156 -0
  40. package/src/__tests__/image-critic-node.test.ts +86 -0
  41. package/src/__tests__/image-mask-mode.test.ts +16 -0
  42. package/src/__tests__/image-ref-limit.test.ts +78 -0
  43. package/src/__tests__/inpaint-region.test.ts +24 -0
  44. package/src/__tests__/input-field-map-parity.test.ts +30 -0
  45. package/src/__tests__/json-evaluator.test.ts +289 -0
  46. package/src/__tests__/json-path.test.ts +64 -0
  47. package/src/__tests__/lip-sync-pricing.test.ts +142 -0
  48. package/src/__tests__/list-merge.test.ts +96 -0
  49. package/src/__tests__/list-sort.test.ts +134 -0
  50. package/src/__tests__/llm-models.test.ts +445 -0
  51. package/src/__tests__/location-mention-slug.test.ts +246 -0
  52. package/src/__tests__/locations-coverage-critic-schema.test.ts +92 -0
  53. package/src/__tests__/loop-delimiter.test.ts +39 -0
  54. package/src/__tests__/lottie-slots.test.ts +245 -0
  55. package/src/__tests__/model-catalog-flux2-resolutions.test.ts +21 -0
  56. package/src/__tests__/model-constants-location.test.ts +20 -0
  57. package/src/__tests__/model-constants.test.ts +122 -0
  58. package/src/__tests__/model-tree.test.ts +86 -0
  59. package/src/__tests__/no-internal-imports.test.ts +25 -0
  60. package/src/__tests__/node-default-mappings.test.ts +175 -0
  61. package/src/__tests__/node-mappable-fields.test.ts +7 -0
  62. package/src/__tests__/node-preset-export.test.ts +46 -0
  63. package/src/__tests__/node-preset-extract.test.ts +166 -0
  64. package/src/__tests__/node-refs-canonical.test.ts +54 -0
  65. package/src/__tests__/node-refs-combine.test.ts +54 -0
  66. package/src/__tests__/node-refs.test.ts +187 -0
  67. package/src/__tests__/node-runtime-keys.test.ts +99 -0
  68. package/src/__tests__/object-aspect-defaults.test.ts +59 -0
  69. package/src/__tests__/parameter-node-value.test.ts +137 -0
  70. package/src/__tests__/pinterest-url.test.ts +35 -0
  71. package/src/__tests__/pipeline-chat.test.ts +110 -0
  72. package/src/__tests__/pipeline-validation.test.ts +98 -0
  73. package/src/__tests__/presentation-utils.test.ts +1137 -0
  74. package/src/__tests__/producer-types.test.ts +47 -0
  75. package/src/__tests__/prompt-length-limits.test.ts +156 -0
  76. package/src/__tests__/provider-directive-defaults.test.ts +46 -0
  77. package/src/__tests__/reduce-strategy-registry.test.ts +43 -0
  78. package/src/__tests__/reference-board-templates.test.ts +33 -0
  79. package/src/__tests__/reference-roles.test.ts +36 -0
  80. package/src/__tests__/resolve-field-mappings.test.ts +110 -0
  81. package/src/__tests__/resolve-pipeline-model.test.ts +76 -0
  82. package/src/__tests__/scene-node-types.test.ts +80 -0
  83. package/src/__tests__/scraper-actors.test.ts +67 -0
  84. package/src/__tests__/seedance-2-catalog.test.ts +18 -0
  85. package/src/__tests__/seedance-2-credit-id.test.ts +23 -0
  86. package/src/__tests__/seedance-aspects.test.ts +52 -0
  87. package/src/__tests__/selector.test.ts +1151 -0
  88. package/src/__tests__/settled-with-limit.test.ts +214 -0
  89. package/src/__tests__/social-media-specs.test.ts +129 -0
  90. package/src/__tests__/sub-workflow-validation.test.ts +88 -0
  91. package/src/__tests__/switchx-pricing.test.ts +28 -0
  92. package/src/__tests__/to-connected-references.test.ts +153 -0
  93. package/src/__tests__/utilities.test.ts +541 -0
  94. package/src/__tests__/video-analysis-pricing.test.ts +58 -0
  95. package/src/__tests__/video-analysis.test.ts +63 -0
  96. package/src/__tests__/video-audio-capability.test.ts +204 -0
  97. package/src/__tests__/video-gen-providers.test.ts +28 -0
  98. package/src/__tests__/video-mode-aliases.test.ts +150 -0
  99. package/src/__tests__/video-ref-limits.test.ts +72 -0
  100. package/src/__tests__/video-utils.test.ts +303 -0
  101. package/src/__tests__/voice-changer-models.test.ts +33 -0
  102. package/src/__tests__/workflow-export-strip.test.ts +46 -0
  103. package/src/ai-avatar-pricing.ts +213 -0
  104. package/src/ancestor-refs.ts +48 -0
  105. package/src/animals.ts +231 -0
  106. package/src/audio-crossfade-curves.ts +73 -0
  107. package/src/audio-fx-presets.ts +64 -0
  108. package/src/avatar-payload-validators.ts +214 -0
  109. package/src/caption-styles.ts +31 -0
  110. package/src/character-aspect-defaults.ts +102 -0
  111. package/src/character-facets.ts +37 -0
  112. package/src/character-mention-slug.ts +166 -0
  113. package/src/character-usage-mode.ts +109 -0
  114. package/src/character-variant-assets.ts +121 -0
  115. package/src/character-voice.ts +151 -0
  116. package/src/cinematic-avatar-pricing.ts +111 -0
  117. package/src/clone-utils.ts +46 -0
  118. package/src/combine-transitions.ts +482 -0
  119. package/src/community.ts +112 -0
  120. package/src/component-types.ts +127 -0
  121. package/src/condition-variables.ts +65 -0
  122. package/src/credit-estimators/index.ts +15 -0
  123. package/src/credit-estimators/video-utils.ts +165 -0
  124. package/src/credit-identifiers.ts +304 -0
  125. package/src/entity-approval-types.ts +31 -0
  126. package/src/entity-aspect-defaults.ts +82 -0
  127. package/src/entity-asset-types.ts +296 -0
  128. package/src/entity-image-handle.ts +36 -0
  129. package/src/extra-refs.ts +139 -0
  130. package/src/featured-entities.ts +136 -0
  131. package/src/film-pricing.ts +117 -0
  132. package/src/filter-condition.ts +250 -0
  133. package/src/flux2-pricing.ts +18 -0
  134. package/src/freecut-protocol.ts +52 -0
  135. package/src/furniture.ts +167 -0
  136. package/src/generate-text-items.ts +15 -0
  137. package/src/generated-results.ts +63 -0
  138. package/src/group-aggregation.ts +75 -0
  139. package/src/hint-graph-types.ts +18 -0
  140. package/src/i18n/action-fx.ar.ts +89 -0
  141. package/src/i18n/action-fx.de.ts +89 -0
  142. package/src/i18n/action-fx.es.ts +89 -0
  143. package/src/i18n/action-fx.fr.ts +89 -0
  144. package/src/i18n/action-fx.he.ts +89 -0
  145. package/src/i18n/action-fx.hi.ts +89 -0
  146. package/src/i18n/action-fx.ja.ts +89 -0
  147. package/src/i18n/action-fx.ko.ts +89 -0
  148. package/src/i18n/action-fx.pt-BR.ts +89 -0
  149. package/src/i18n/action-fx.ru.ts +89 -0
  150. package/src/i18n/action-fx.zh-CN.ts +89 -0
  151. package/src/i18n/aesthetic.ar.ts +170 -0
  152. package/src/i18n/aesthetic.de.ts +48 -0
  153. package/src/i18n/aesthetic.es.ts +169 -0
  154. package/src/i18n/aesthetic.fr.ts +52 -0
  155. package/src/i18n/aesthetic.he.ts +169 -0
  156. package/src/i18n/aesthetic.hi.ts +55 -0
  157. package/src/i18n/aesthetic.ja.ts +165 -0
  158. package/src/i18n/aesthetic.ko.ts +169 -0
  159. package/src/i18n/aesthetic.pt-BR.ts +148 -0
  160. package/src/i18n/aesthetic.ru.ts +155 -0
  161. package/src/i18n/aesthetic.zh-CN.ts +172 -0
  162. package/src/i18n/animals.ar.ts +145 -0
  163. package/src/i18n/animals.de.ts +144 -0
  164. package/src/i18n/animals.es.ts +158 -0
  165. package/src/i18n/animals.fr.ts +144 -0
  166. package/src/i18n/animals.he.ts +155 -0
  167. package/src/i18n/animals.hi.ts +157 -0
  168. package/src/i18n/animals.ja.ts +159 -0
  169. package/src/i18n/animals.ko.ts +159 -0
  170. package/src/i18n/animals.pt-BR.ts +157 -0
  171. package/src/i18n/animals.ru.ts +155 -0
  172. package/src/i18n/animals.zh-CN.ts +155 -0
  173. package/src/i18n/atmosphere.ar.ts +49 -0
  174. package/src/i18n/atmosphere.de.ts +47 -0
  175. package/src/i18n/atmosphere.es.ts +50 -0
  176. package/src/i18n/atmosphere.fr.ts +47 -0
  177. package/src/i18n/atmosphere.he.ts +47 -0
  178. package/src/i18n/atmosphere.hi.ts +49 -0
  179. package/src/i18n/atmosphere.ja.ts +49 -0
  180. package/src/i18n/atmosphere.ko.ts +49 -0
  181. package/src/i18n/atmosphere.pt-BR.ts +49 -0
  182. package/src/i18n/atmosphere.ru.ts +47 -0
  183. package/src/i18n/atmosphere.zh-CN.ts +152 -0
  184. package/src/i18n/backdrop.ar.ts +53 -0
  185. package/src/i18n/backdrop.de.ts +46 -0
  186. package/src/i18n/backdrop.es.ts +54 -0
  187. package/src/i18n/backdrop.fr.ts +52 -0
  188. package/src/i18n/backdrop.he.ts +51 -0
  189. package/src/i18n/backdrop.hi.ts +59 -0
  190. package/src/i18n/backdrop.ja.ts +61 -0
  191. package/src/i18n/backdrop.ko.ts +59 -0
  192. package/src/i18n/backdrop.pt-BR.ts +59 -0
  193. package/src/i18n/backdrop.ru.ts +57 -0
  194. package/src/i18n/backdrop.zh-CN.ts +57 -0
  195. package/src/i18n/camera-format.ar.ts +40 -0
  196. package/src/i18n/camera-format.de.ts +37 -0
  197. package/src/i18n/camera-format.es.ts +41 -0
  198. package/src/i18n/camera-format.fr.ts +37 -0
  199. package/src/i18n/camera-format.he.ts +37 -0
  200. package/src/i18n/camera-format.hi.ts +42 -0
  201. package/src/i18n/camera-format.ja.ts +37 -0
  202. package/src/i18n/camera-format.ko.ts +37 -0
  203. package/src/i18n/camera-format.pt-BR.ts +46 -0
  204. package/src/i18n/camera-format.ru.ts +42 -0
  205. package/src/i18n/camera-format.zh-CN.ts +42 -0
  206. package/src/i18n/camera-motions.ar.ts +86 -0
  207. package/src/i18n/camera-motions.de.ts +74 -0
  208. package/src/i18n/camera-motions.es.ts +86 -0
  209. package/src/i18n/camera-motions.fr.ts +86 -0
  210. package/src/i18n/camera-motions.he.ts +86 -0
  211. package/src/i18n/camera-motions.hi.ts +99 -0
  212. package/src/i18n/camera-motions.ja.ts +99 -0
  213. package/src/i18n/camera-motions.ko.ts +99 -0
  214. package/src/i18n/camera-motions.pt-BR.ts +99 -0
  215. package/src/i18n/camera-motions.ru.ts +99 -0
  216. package/src/i18n/camera-motions.zh-CN.ts +99 -0
  217. package/src/i18n/character-fx.ar.ts +72 -0
  218. package/src/i18n/character-fx.de.ts +72 -0
  219. package/src/i18n/character-fx.es.ts +72 -0
  220. package/src/i18n/character-fx.fr.ts +72 -0
  221. package/src/i18n/character-fx.he.ts +72 -0
  222. package/src/i18n/character-fx.hi.ts +72 -0
  223. package/src/i18n/character-fx.ja.ts +72 -0
  224. package/src/i18n/character-fx.ko.ts +72 -0
  225. package/src/i18n/character-fx.pt-BR.ts +72 -0
  226. package/src/i18n/character-fx.ru.ts +72 -0
  227. package/src/i18n/character-fx.zh-CN.ts +72 -0
  228. package/src/i18n/color-look.ar.ts +50 -0
  229. package/src/i18n/color-look.de.ts +47 -0
  230. package/src/i18n/color-look.es.ts +50 -0
  231. package/src/i18n/color-look.fr.ts +50 -0
  232. package/src/i18n/color-look.he.ts +49 -0
  233. package/src/i18n/color-look.hi.ts +52 -0
  234. package/src/i18n/color-look.ja.ts +54 -0
  235. package/src/i18n/color-look.ko.ts +54 -0
  236. package/src/i18n/color-look.pt-BR.ts +54 -0
  237. package/src/i18n/color-look.ru.ts +52 -0
  238. package/src/i18n/color-look.zh-CN.ts +53 -0
  239. package/src/i18n/composition-effects.ar.ts +26 -0
  240. package/src/i18n/composition-effects.de.ts +25 -0
  241. package/src/i18n/composition-effects.es.ts +27 -0
  242. package/src/i18n/composition-effects.fr.ts +25 -0
  243. package/src/i18n/composition-effects.he.ts +25 -0
  244. package/src/i18n/composition-effects.hi.ts +27 -0
  245. package/src/i18n/composition-effects.ja.ts +27 -0
  246. package/src/i18n/composition-effects.ko.ts +27 -0
  247. package/src/i18n/composition-effects.pt-BR.ts +25 -0
  248. package/src/i18n/composition-effects.ru.ts +82 -0
  249. package/src/i18n/composition-effects.zh-CN.ts +25 -0
  250. package/src/i18n/era.ar.ts +37 -0
  251. package/src/i18n/era.de.ts +34 -0
  252. package/src/i18n/era.es.ts +37 -0
  253. package/src/i18n/era.fr.ts +37 -0
  254. package/src/i18n/era.he.ts +36 -0
  255. package/src/i18n/era.hi.ts +39 -0
  256. package/src/i18n/era.ja.ts +41 -0
  257. package/src/i18n/era.ko.ts +39 -0
  258. package/src/i18n/era.pt-BR.ts +41 -0
  259. package/src/i18n/era.ru.ts +121 -0
  260. package/src/i18n/era.zh-CN.ts +39 -0
  261. package/src/i18n/exposure-settings.ar.ts +28 -0
  262. package/src/i18n/exposure-settings.de.ts +26 -0
  263. package/src/i18n/exposure-settings.es.ts +28 -0
  264. package/src/i18n/exposure-settings.fr.ts +29 -0
  265. package/src/i18n/exposure-settings.he.ts +28 -0
  266. package/src/i18n/exposure-settings.hi.ts +31 -0
  267. package/src/i18n/exposure-settings.ja.ts +31 -0
  268. package/src/i18n/exposure-settings.ko.ts +31 -0
  269. package/src/i18n/exposure-settings.pt-BR.ts +31 -0
  270. package/src/i18n/exposure-settings.ru.ts +31 -0
  271. package/src/i18n/exposure-settings.zh-CN.ts +31 -0
  272. package/src/i18n/framing.ar.ts +78 -0
  273. package/src/i18n/framing.de.ts +73 -0
  274. package/src/i18n/framing.es.ts +78 -0
  275. package/src/i18n/framing.fr.ts +78 -0
  276. package/src/i18n/framing.he.ts +77 -0
  277. package/src/i18n/framing.hi.ts +82 -0
  278. package/src/i18n/framing.ja.ts +84 -0
  279. package/src/i18n/framing.ko.ts +82 -0
  280. package/src/i18n/framing.pt-BR.ts +84 -0
  281. package/src/i18n/framing.ru.ts +82 -0
  282. package/src/i18n/framing.zh-CN.ts +82 -0
  283. package/src/i18n/furniture.ar.ts +92 -0
  284. package/src/i18n/furniture.de.ts +93 -0
  285. package/src/i18n/furniture.es.ts +101 -0
  286. package/src/i18n/furniture.fr.ts +93 -0
  287. package/src/i18n/furniture.he.ts +101 -0
  288. package/src/i18n/furniture.hi.ts +101 -0
  289. package/src/i18n/furniture.ja.ts +101 -0
  290. package/src/i18n/furniture.ko.ts +101 -0
  291. package/src/i18n/furniture.pt-BR.ts +101 -0
  292. package/src/i18n/furniture.ru.ts +101 -0
  293. package/src/i18n/furniture.zh-CN.ts +101 -0
  294. package/src/i18n/held-prop.ar.ts +74 -0
  295. package/src/i18n/held-prop.de.ts +65 -0
  296. package/src/i18n/held-prop.es.ts +83 -0
  297. package/src/i18n/held-prop.fr.ts +74 -0
  298. package/src/i18n/held-prop.he.ts +73 -0
  299. package/src/i18n/held-prop.hi.ts +82 -0
  300. package/src/i18n/held-prop.ja.ts +84 -0
  301. package/src/i18n/held-prop.ko.ts +84 -0
  302. package/src/i18n/held-prop.pt-BR.ts +84 -0
  303. package/src/i18n/held-prop.ru.ts +82 -0
  304. package/src/i18n/held-prop.zh-CN.ts +82 -0
  305. package/src/i18n/index.ts +208 -0
  306. package/src/i18n/instrumentation.ar.ts +195 -0
  307. package/src/i18n/instrumentation.de.ts +195 -0
  308. package/src/i18n/instrumentation.es.ts +195 -0
  309. package/src/i18n/instrumentation.fr.ts +195 -0
  310. package/src/i18n/instrumentation.he.ts +195 -0
  311. package/src/i18n/instrumentation.hi.ts +195 -0
  312. package/src/i18n/instrumentation.ja.ts +195 -0
  313. package/src/i18n/instrumentation.ko.ts +195 -0
  314. package/src/i18n/instrumentation.pt-BR.ts +195 -0
  315. package/src/i18n/instrumentation.ru.ts +195 -0
  316. package/src/i18n/instrumentation.zh-CN.ts +195 -0
  317. package/src/i18n/lens.ar.ts +24 -0
  318. package/src/i18n/lens.de.ts +24 -0
  319. package/src/i18n/lens.es.ts +24 -0
  320. package/src/i18n/lens.fr.ts +24 -0
  321. package/src/i18n/lens.he.ts +24 -0
  322. package/src/i18n/lens.hi.ts +24 -0
  323. package/src/i18n/lens.ja.ts +24 -0
  324. package/src/i18n/lens.ko.ts +24 -0
  325. package/src/i18n/lens.pt-BR.ts +24 -0
  326. package/src/i18n/lens.ru.ts +25 -0
  327. package/src/i18n/lens.zh-CN.ts +24 -0
  328. package/src/i18n/lighting.ar.ts +86 -0
  329. package/src/i18n/lighting.de.ts +84 -0
  330. package/src/i18n/lighting.es.ts +89 -0
  331. package/src/i18n/lighting.fr.ts +84 -0
  332. package/src/i18n/lighting.he.ts +88 -0
  333. package/src/i18n/lighting.hi.ts +90 -0
  334. package/src/i18n/lighting.ja.ts +90 -0
  335. package/src/i18n/lighting.ko.ts +90 -0
  336. package/src/i18n/lighting.pt-BR.ts +90 -0
  337. package/src/i18n/lighting.ru.ts +88 -0
  338. package/src/i18n/lighting.zh-CN.ts +92 -0
  339. package/src/i18n/loop-subject.ar.ts +39 -0
  340. package/src/i18n/loop-subject.de.ts +39 -0
  341. package/src/i18n/loop-subject.es.ts +39 -0
  342. package/src/i18n/loop-subject.fr.ts +39 -0
  343. package/src/i18n/loop-subject.he.ts +39 -0
  344. package/src/i18n/loop-subject.hi.ts +39 -0
  345. package/src/i18n/loop-subject.ja.ts +39 -0
  346. package/src/i18n/loop-subject.ko.ts +39 -0
  347. package/src/i18n/loop-subject.pt-BR.ts +39 -0
  348. package/src/i18n/loop-subject.ru.ts +39 -0
  349. package/src/i18n/loop-subject.zh-CN.ts +39 -0
  350. package/src/i18n/materials.ar.ts +80 -0
  351. package/src/i18n/materials.de.ts +80 -0
  352. package/src/i18n/materials.es.ts +87 -0
  353. package/src/i18n/materials.fr.ts +80 -0
  354. package/src/i18n/materials.he.ts +86 -0
  355. package/src/i18n/materials.hi.ts +86 -0
  356. package/src/i18n/materials.ja.ts +88 -0
  357. package/src/i18n/materials.ko.ts +88 -0
  358. package/src/i18n/materials.pt-BR.ts +88 -0
  359. package/src/i18n/materials.ru.ts +86 -0
  360. package/src/i18n/materials.zh-CN.ts +86 -0
  361. package/src/i18n/mood.ar.ts +61 -0
  362. package/src/i18n/mood.de.ts +61 -0
  363. package/src/i18n/mood.es.ts +66 -0
  364. package/src/i18n/mood.fr.ts +61 -0
  365. package/src/i18n/mood.he.ts +64 -0
  366. package/src/i18n/mood.hi.ts +66 -0
  367. package/src/i18n/mood.ja.ts +66 -0
  368. package/src/i18n/mood.ko.ts +66 -0
  369. package/src/i18n/mood.pt-BR.ts +64 -0
  370. package/src/i18n/mood.ru.ts +64 -0
  371. package/src/i18n/mood.zh-CN.ts +64 -0
  372. package/src/i18n/music-genre.ar.ts +302 -0
  373. package/src/i18n/music-genre.de.ts +302 -0
  374. package/src/i18n/music-genre.es.ts +302 -0
  375. package/src/i18n/music-genre.fr.ts +302 -0
  376. package/src/i18n/music-genre.he.ts +302 -0
  377. package/src/i18n/music-genre.hi.ts +302 -0
  378. package/src/i18n/music-genre.ja.ts +302 -0
  379. package/src/i18n/music-genre.ko.ts +302 -0
  380. package/src/i18n/music-genre.pt-BR.ts +302 -0
  381. package/src/i18n/music-genre.ru.ts +302 -0
  382. package/src/i18n/music-genre.zh-CN.ts +302 -0
  383. package/src/i18n/music-mood.ar.ts +75 -0
  384. package/src/i18n/music-mood.de.ts +75 -0
  385. package/src/i18n/music-mood.es.ts +75 -0
  386. package/src/i18n/music-mood.fr.ts +75 -0
  387. package/src/i18n/music-mood.he.ts +75 -0
  388. package/src/i18n/music-mood.hi.ts +75 -0
  389. package/src/i18n/music-mood.ja.ts +75 -0
  390. package/src/i18n/music-mood.ko.ts +75 -0
  391. package/src/i18n/music-mood.pt-BR.ts +75 -0
  392. package/src/i18n/music-mood.ru.ts +75 -0
  393. package/src/i18n/music-mood.zh-CN.ts +75 -0
  394. package/src/i18n/person.ar.ts +638 -0
  395. package/src/i18n/person.de.ts +629 -0
  396. package/src/i18n/person.es.ts +645 -0
  397. package/src/i18n/person.fr.ts +621 -0
  398. package/src/i18n/person.he.ts +656 -0
  399. package/src/i18n/person.hi.ts +654 -0
  400. package/src/i18n/person.ja.ts +662 -0
  401. package/src/i18n/person.ko.ts +662 -0
  402. package/src/i18n/person.pt-BR.ts +656 -0
  403. package/src/i18n/person.ru.ts +656 -0
  404. package/src/i18n/person.zh-CN.ts +656 -0
  405. package/src/i18n/photo-genre.ar.ts +58 -0
  406. package/src/i18n/photo-genre.de.ts +52 -0
  407. package/src/i18n/photo-genre.es.ts +64 -0
  408. package/src/i18n/photo-genre.fr.ts +58 -0
  409. package/src/i18n/photo-genre.he.ts +62 -0
  410. package/src/i18n/photo-genre.hi.ts +63 -0
  411. package/src/i18n/photo-genre.ja.ts +65 -0
  412. package/src/i18n/photo-genre.ko.ts +63 -0
  413. package/src/i18n/photo-genre.pt-BR.ts +65 -0
  414. package/src/i18n/photo-genre.ru.ts +63 -0
  415. package/src/i18n/photo-genre.zh-CN.ts +63 -0
  416. package/src/i18n/photographer.ar.ts +75 -0
  417. package/src/i18n/photographer.de.ts +74 -0
  418. package/src/i18n/photographer.es.ts +77 -0
  419. package/src/i18n/photographer.fr.ts +77 -0
  420. package/src/i18n/photographer.he.ts +78 -0
  421. package/src/i18n/photographer.hi.ts +80 -0
  422. package/src/i18n/photographer.ja.ts +84 -0
  423. package/src/i18n/photographer.ko.ts +84 -0
  424. package/src/i18n/photographer.pt-BR.ts +83 -0
  425. package/src/i18n/photographer.ru.ts +78 -0
  426. package/src/i18n/photographer.zh-CN.ts +78 -0
  427. package/src/i18n/pose.ar.ts +95 -0
  428. package/src/i18n/pose.de.ts +96 -0
  429. package/src/i18n/pose.es.ts +104 -0
  430. package/src/i18n/pose.fr.ts +96 -0
  431. package/src/i18n/pose.he.ts +104 -0
  432. package/src/i18n/pose.hi.ts +104 -0
  433. package/src/i18n/pose.ja.ts +104 -0
  434. package/src/i18n/pose.ko.ts +104 -0
  435. package/src/i18n/pose.pt-BR.ts +104 -0
  436. package/src/i18n/pose.ru.ts +104 -0
  437. package/src/i18n/pose.zh-CN.ts +104 -0
  438. package/src/i18n/post-process-effects.ar.ts +25 -0
  439. package/src/i18n/post-process-effects.de.ts +24 -0
  440. package/src/i18n/post-process-effects.es.ts +26 -0
  441. package/src/i18n/post-process-effects.fr.ts +24 -0
  442. package/src/i18n/post-process-effects.he.ts +24 -0
  443. package/src/i18n/post-process-effects.hi.ts +26 -0
  444. package/src/i18n/post-process-effects.ja.ts +26 -0
  445. package/src/i18n/post-process-effects.ko.ts +26 -0
  446. package/src/i18n/post-process-effects.pt-BR.ts +24 -0
  447. package/src/i18n/post-process-effects.ru.ts +24 -0
  448. package/src/i18n/post-process-effects.zh-CN.ts +24 -0
  449. package/src/i18n/render-quality.ar.ts +34 -0
  450. package/src/i18n/render-quality.de.ts +30 -0
  451. package/src/i18n/render-quality.es.ts +35 -0
  452. package/src/i18n/render-quality.fr.ts +34 -0
  453. package/src/i18n/render-quality.he.ts +33 -0
  454. package/src/i18n/render-quality.hi.ts +39 -0
  455. package/src/i18n/render-quality.ja.ts +39 -0
  456. package/src/i18n/render-quality.ko.ts +39 -0
  457. package/src/i18n/render-quality.pt-BR.ts +37 -0
  458. package/src/i18n/render-quality.ru.ts +37 -0
  459. package/src/i18n/render-quality.zh-CN.ts +37 -0
  460. package/src/i18n/seasons.ar.ts +10 -0
  461. package/src/i18n/seasons.de.ts +10 -0
  462. package/src/i18n/seasons.es.ts +10 -0
  463. package/src/i18n/seasons.fr.ts +10 -0
  464. package/src/i18n/seasons.he.ts +10 -0
  465. package/src/i18n/seasons.hi.ts +10 -0
  466. package/src/i18n/seasons.ja.ts +10 -0
  467. package/src/i18n/seasons.ko.ts +10 -0
  468. package/src/i18n/seasons.pt-BR.ts +10 -0
  469. package/src/i18n/seasons.ru.ts +10 -0
  470. package/src/i18n/seasons.zh-CN.ts +10 -0
  471. package/src/i18n/setting.ar.ts +73 -0
  472. package/src/i18n/setting.de.ts +73 -0
  473. package/src/i18n/setting.es.ts +77 -0
  474. package/src/i18n/setting.fr.ts +73 -0
  475. package/src/i18n/setting.he.ts +76 -0
  476. package/src/i18n/setting.hi.ts +76 -0
  477. package/src/i18n/setting.ja.ts +78 -0
  478. package/src/i18n/setting.ko.ts +76 -0
  479. package/src/i18n/setting.pt-BR.ts +78 -0
  480. package/src/i18n/setting.ru.ts +76 -0
  481. package/src/i18n/setting.zh-CN.ts +76 -0
  482. package/src/i18n/style.ar.ts +55 -0
  483. package/src/i18n/style.de.ts +54 -0
  484. package/src/i18n/style.es.ts +54 -0
  485. package/src/i18n/style.fr.ts +54 -0
  486. package/src/i18n/style.he.ts +54 -0
  487. package/src/i18n/style.hi.ts +54 -0
  488. package/src/i18n/style.ja.ts +54 -0
  489. package/src/i18n/style.ko.ts +54 -0
  490. package/src/i18n/style.pt-BR.ts +56 -0
  491. package/src/i18n/style.ru.ts +54 -0
  492. package/src/i18n/style.zh-CN.ts +54 -0
  493. package/src/i18n/styling.ar.ts +295 -0
  494. package/src/i18n/styling.de.ts +285 -0
  495. package/src/i18n/styling.es.ts +317 -0
  496. package/src/i18n/styling.fr.ts +285 -0
  497. package/src/i18n/styling.he.ts +307 -0
  498. package/src/i18n/styling.hi.ts +323 -0
  499. package/src/i18n/styling.ja.ts +317 -0
  500. package/src/i18n/styling.ko.ts +311 -0
  501. package/src/i18n/styling.pt-BR.ts +301 -0
  502. package/src/i18n/styling.ru.ts +301 -0
  503. package/src/i18n/styling.zh-CN.ts +307 -0
  504. package/src/i18n/temporal.ar.ts +31 -0
  505. package/src/i18n/temporal.de.ts +24 -0
  506. package/src/i18n/temporal.es.ts +27 -0
  507. package/src/i18n/temporal.fr.ts +28 -0
  508. package/src/i18n/temporal.he.ts +31 -0
  509. package/src/i18n/temporal.hi.ts +31 -0
  510. package/src/i18n/temporal.ja.ts +31 -0
  511. package/src/i18n/temporal.ko.ts +31 -0
  512. package/src/i18n/temporal.pt-BR.ts +31 -0
  513. package/src/i18n/temporal.ru.ts +31 -0
  514. package/src/i18n/temporal.zh-CN.ts +31 -0
  515. package/src/i18n/transitions.ar.ts +97 -0
  516. package/src/i18n/transitions.de.ts +97 -0
  517. package/src/i18n/transitions.es.ts +97 -0
  518. package/src/i18n/transitions.fr.ts +97 -0
  519. package/src/i18n/transitions.he.ts +97 -0
  520. package/src/i18n/transitions.hi.ts +97 -0
  521. package/src/i18n/transitions.ja.ts +97 -0
  522. package/src/i18n/transitions.ko.ts +97 -0
  523. package/src/i18n/transitions.pt-BR.ts +97 -0
  524. package/src/i18n/transitions.ru.ts +97 -0
  525. package/src/i18n/transitions.zh-CN.ts +97 -0
  526. package/src/i18n/types.ts +158 -0
  527. package/src/i18n/vehicles.ar.ts +137 -0
  528. package/src/i18n/vehicles.de.ts +125 -0
  529. package/src/i18n/vehicles.es.ts +138 -0
  530. package/src/i18n/vehicles.fr.ts +125 -0
  531. package/src/i18n/vehicles.he.ts +136 -0
  532. package/src/i18n/vehicles.hi.ts +138 -0
  533. package/src/i18n/vehicles.ja.ts +138 -0
  534. package/src/i18n/vehicles.ko.ts +138 -0
  535. package/src/i18n/vehicles.pt-BR.ts +136 -0
  536. package/src/i18n/vehicles.ru.ts +136 -0
  537. package/src/i18n/vehicles.zh-CN.ts +136 -0
  538. package/src/i18n/voice-character.ar.ts +126 -0
  539. package/src/i18n/voice-character.de.ts +126 -0
  540. package/src/i18n/voice-character.es.ts +126 -0
  541. package/src/i18n/voice-character.fr.ts +126 -0
  542. package/src/i18n/voice-character.he.ts +126 -0
  543. package/src/i18n/voice-character.hi.ts +126 -0
  544. package/src/i18n/voice-character.ja.ts +126 -0
  545. package/src/i18n/voice-character.ko.ts +126 -0
  546. package/src/i18n/voice-character.pt-BR.ts +126 -0
  547. package/src/i18n/voice-character.ru.ts +126 -0
  548. package/src/i18n/voice-character.zh-CN.ts +126 -0
  549. package/src/i18n/voice-delivery.ar.ts +77 -0
  550. package/src/i18n/voice-delivery.de.ts +77 -0
  551. package/src/i18n/voice-delivery.es.ts +77 -0
  552. package/src/i18n/voice-delivery.fr.ts +77 -0
  553. package/src/i18n/voice-delivery.he.ts +77 -0
  554. package/src/i18n/voice-delivery.hi.ts +77 -0
  555. package/src/i18n/voice-delivery.ja.ts +77 -0
  556. package/src/i18n/voice-delivery.ko.ts +77 -0
  557. package/src/i18n/voice-delivery.pt-BR.ts +77 -0
  558. package/src/i18n/voice-delivery.ru.ts +77 -0
  559. package/src/i18n/voice-delivery.zh-CN.ts +77 -0
  560. package/src/i18n/weapons.ar.ts +115 -0
  561. package/src/i18n/weapons.de.ts +114 -0
  562. package/src/i18n/weapons.es.ts +116 -0
  563. package/src/i18n/weapons.fr.ts +103 -0
  564. package/src/i18n/weapons.he.ts +114 -0
  565. package/src/i18n/weapons.hi.ts +116 -0
  566. package/src/i18n/weapons.ja.ts +116 -0
  567. package/src/i18n/weapons.ko.ts +116 -0
  568. package/src/i18n/weapons.pt-BR.ts +114 -0
  569. package/src/i18n/weapons.ru.ts +114 -0
  570. package/src/i18n/weapons.zh-CN.ts +114 -0
  571. package/src/image-critic-node.ts +61 -0
  572. package/src/image-critic-types.ts +40 -0
  573. package/src/index.ts +866 -0
  574. package/src/inject-upstream.ts +15 -0
  575. package/src/inpaint-region.ts +51 -0
  576. package/src/json-evaluator.ts +732 -0
  577. package/src/json-path.ts +52 -0
  578. package/src/lip-sync-pricing.ts +90 -0
  579. package/src/list-merge.ts +40 -0
  580. package/src/list-sort.ts +122 -0
  581. package/src/list-source-resolver.ts +50 -0
  582. package/src/llm-models.ts +245 -0
  583. package/src/location-mention-slug.ts +291 -0
  584. package/src/location-preset-catalog-map.ts +128 -0
  585. package/src/loop-delimiter.ts +73 -0
  586. package/src/lora-routing.ts +95 -0
  587. package/src/lottie-overlay-catalog.ts +175 -0
  588. package/src/lottie-slots.ts +309 -0
  589. package/src/model-catalog.ts +2386 -0
  590. package/src/model-constants.ts +1910 -0
  591. package/src/model-tree.ts +120 -0
  592. package/src/monetization.ts +15 -0
  593. package/src/multi-pick.ts +42 -0
  594. package/src/node-default-mappings.ts +262 -0
  595. package/src/node-mappable-fields.ts +70 -0
  596. package/src/node-preset-export.ts +56 -0
  597. package/src/node-preset-extract.ts +147 -0
  598. package/src/node-refs.ts +253 -0
  599. package/src/node-runtime-keys.ts +117 -0
  600. package/src/object-aspect-defaults.ts +72 -0
  601. package/src/object-picker-types.ts +22 -0
  602. package/src/parameter-node-value.ts +284 -0
  603. package/src/pinterest-url.ts +28 -0
  604. package/src/pipeline-chat.ts +72 -0
  605. package/src/pipeline-defaults.ts +318 -0
  606. package/src/pipeline-events.ts +162 -0
  607. package/src/pipeline-state-types.ts +196 -0
  608. package/src/pipeline-types.ts +647 -0
  609. package/src/pipeline-validation.ts +87 -0
  610. package/src/presentation-types.ts +23 -0
  611. package/src/presentation-utils.ts +397 -0
  612. package/src/producer-types.ts +188 -0
  613. package/src/progress-curve.ts +99 -0
  614. package/src/provider-directive-defaults.ts +69 -0
  615. package/src/reduce-strategy-registry.ts +121 -0
  616. package/src/reference-board-templates.ts +81 -0
  617. package/src/reference-roles.ts +153 -0
  618. package/src/reference-sheet/__tests__/board-to-column.test.ts +20 -0
  619. package/src/reference-sheet/__tests__/catalog.test.ts +50 -0
  620. package/src/reference-sheet/__tests__/cost.test.ts +38 -0
  621. package/src/reference-sheet/__tests__/no-drift.test.ts +28 -0
  622. package/src/reference-sheet/__tests__/panel-plan.test.ts +61 -0
  623. package/src/reference-sheet/__tests__/panel-prompts.test.ts +17 -0
  624. package/src/reference-sheet/__tests__/plan-generation.test.ts +72 -0
  625. package/src/reference-sheet/__tests__/presets.test.ts +54 -0
  626. package/src/reference-sheet/__tests__/types.test.ts +24 -0
  627. package/src/reference-sheet/catalog.ts +144 -0
  628. package/src/reference-sheet/cost.ts +37 -0
  629. package/src/reference-sheet/credit-id.ts +7 -0
  630. package/src/reference-sheet/index.ts +8 -0
  631. package/src/reference-sheet/panel-plan.ts +65 -0
  632. package/src/reference-sheet/panel-prompts.ts +14 -0
  633. package/src/reference-sheet/plan-generation.ts +79 -0
  634. package/src/reference-sheet/presets.ts +77 -0
  635. package/src/reference-sheet/types.ts +92 -0
  636. package/src/repeat-types.ts +97 -0
  637. package/src/resolve-field-mappings.ts +119 -0
  638. package/src/route-filter.ts +80 -0
  639. package/src/scene-helper-types.ts +249 -0
  640. package/src/scene-node-types.ts +281 -0
  641. package/src/scraper-actors.ts +57 -0
  642. package/src/scraper-output-schemas.ts +25 -0
  643. package/src/seasons.ts +45 -0
  644. package/src/selector.ts +864 -0
  645. package/src/settled-with-limit.ts +42 -0
  646. package/src/shot-element.ts +43 -0
  647. package/src/social-media-specs.ts +121 -0
  648. package/src/social-post.ts +24 -0
  649. package/src/sub-workflow-validation.ts +78 -0
  650. package/src/supported-fonts.ts +40 -0
  651. package/src/surround.ts +113 -0
  652. package/src/switchx-pricing.ts +33 -0
  653. package/src/text-separators.ts +59 -0
  654. package/src/to-connected-references.ts +77 -0
  655. package/src/types.ts +272 -0
  656. package/src/variant-job-id.ts +17 -0
  657. package/src/vehicles.ts +213 -0
  658. package/src/video-analysis-pricing.ts +74 -0
  659. package/src/video-analysis.ts +127 -0
  660. package/src/video-duration.ts +25 -0
  661. package/src/voice-changer-models.ts +36 -0
  662. package/src/voice-matcher-types.ts +37 -0
  663. package/src/voices.ts +92 -0
  664. package/src/weapons.ts +190 -0
  665. package/src/workflow-export.ts +153 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Models-tab data source: maps each catalog model to the node it creates
3
+ * (`modelToNodeTarget`) and groups node-creatable models into product lines
4
+ * (`buildModelTree`). Consumed by the add-node popup's Models tab. Pure — derives
5
+ * everything from `MODEL_CATALOG` + the provider enums, so models added to the
6
+ * catalog/enums flow through automatically.
7
+ */
8
+ import { MODEL_CATALOG, type ModelKind, type ModelMode } from "./model-catalog.js"
9
+ import {
10
+ IMAGE_GEN_PROVIDERS, VIDEO_GEN_PROVIDERS, IMAGE_TO_VIDEO_PROVIDERS, TEXT_TO_VIDEO_PROVIDERS,
11
+ UPSCALE_IMAGE_PROVIDERS, VIDEO_UPSCALE_PROVIDERS, MODIFY_IMAGE_PROVIDERS, IMAGE_EDIT_PROVIDERS,
12
+ VIDEO_TO_VIDEO_PROVIDERS, EXTEND_VIDEO_PROVIDERS, MOTION_TRANSFER_PROVIDERS, LIP_SYNC_PROVIDERS,
13
+ FACE_SWAP_PROVIDERS, TTS_PROVIDERS, TEXT_TO_AUDIO_PROVIDERS, TRANSCRIBE_PROVIDERS, MUSIC_PROVIDERS,
14
+ } from "./model-constants.js"
15
+
16
+ export interface ModelNodeTarget {
17
+ nodeType: string
18
+ field?: "provider" | "model"
19
+ value?: string
20
+ }
21
+ export interface ModelTreeVariant extends ModelNodeTarget {
22
+ id: string
23
+ label: string
24
+ kind: ModelKind
25
+ }
26
+ export interface ModelTreeLine {
27
+ series: string
28
+ family: string
29
+ kind: ModelKind
30
+ models: ModelTreeVariant[]
31
+ }
32
+
33
+ // A model id that is a valid provider-enum value gets a node + provider preset.
34
+ const ENUM_TARGETS: ReadonlyArray<readonly [readonly string[], string]> = [
35
+ [IMAGE_GEN_PROVIDERS, "generate-image"],
36
+ [VIDEO_GEN_PROVIDERS, "generate-video"],
37
+ [IMAGE_TO_VIDEO_PROVIDERS, "generate-video"],
38
+ [TEXT_TO_VIDEO_PROVIDERS, "generate-video"],
39
+ [UPSCALE_IMAGE_PROVIDERS, "upscale-image"],
40
+ [VIDEO_UPSCALE_PROVIDERS, "video-upscale"],
41
+ [MODIFY_IMAGE_PROVIDERS, "modify-image"],
42
+ [IMAGE_EDIT_PROVIDERS, "modify-image"],
43
+ [VIDEO_TO_VIDEO_PROVIDERS, "video-to-video"],
44
+ [EXTEND_VIDEO_PROVIDERS, "extend-video"],
45
+ [MOTION_TRANSFER_PROVIDERS, "motion-transfer"],
46
+ [LIP_SYNC_PROVIDERS, "lip-sync"],
47
+ [FACE_SWAP_PROVIDERS, "face-swap"],
48
+ [TTS_PROVIDERS, "text-to-speech"],
49
+ [TEXT_TO_AUDIO_PROVIDERS, "text-to-audio"],
50
+ [TRANSCRIBE_PROVIDERS, "transcribe"],
51
+ [MUSIC_PROVIDERS, "suno-generate"],
52
+ ]
53
+
54
+ // Fallback by the catalog's own `modes`, for models whose id is NOT a provider-enum
55
+ // value — single-provider utility nodes (voice-design, dubbing, …) and catalog models
56
+ // that no node exposes as a provider option. These create a bare node of the right
57
+ // type (no provider preset — the user picks the model inside the node).
58
+ const MODE_TO_NODE: Readonly<Partial<Record<ModelMode, string>>> = {
59
+ "t2i": "generate-image", "i2i": "modify-image", "edit": "modify-image", "remove-bg": "modify-image",
60
+ "t2v": "generate-video", "i2v": "generate-video", "v2v": "video-to-video", "extend": "extend-video",
61
+ "upscale": "upscale-image", "video-upscale": "video-upscale", "motion-transfer": "motion-transfer",
62
+ "lip-sync": "lip-sync", "tts": "text-to-speech", "sfx": "text-to-audio",
63
+ "music": "suno-generate", "voice-design": "voice-design", "voice-changer": "voice-changer",
64
+ "isolation": "audio-isolation", "dubbing": "dubbing", "forced-alignment": "forced-alignment", "stt": "transcribe",
65
+ "video-analysis": "video-analysis",
66
+ }
67
+
68
+ export function modelToNodeTarget(modelId: string): ModelNodeTarget | null {
69
+ const entry = MODEL_CATALOG[modelId]
70
+ if (!entry) return null
71
+ // Resolve the target node: a valid provider-enum value wins, else the catalog's modes.
72
+ const enumMatch = ENUM_TARGETS.find(([providers]) => providers.includes(modelId))
73
+ const nodeType = enumMatch?.[1] ?? entry.modes.map((m) => MODE_TO_NODE[m]).find(Boolean)
74
+ if (!nodeType) return null
75
+ // suno-generate stores its model in `data.model` (a V-code carried on the catalog
76
+ // entry as `dataValue`), not as a `provider` id. Every other node takes a `provider`
77
+ // preset when the id is a valid enum value, and a bare node otherwise.
78
+ if (nodeType === "suno-generate") {
79
+ return entry.dataValue ? { nodeType, field: "model", value: entry.dataValue } : { nodeType }
80
+ }
81
+ return enumMatch ? { nodeType, field: "provider", value: modelId } : { nodeType }
82
+ }
83
+
84
+ /**
85
+ * Flat, query-filtered model variants for the add-node search. The single source
86
+ * of truth shared by the Models tab/category browser and every tab's search
87
+ * (image/video/audio narrow by `kind`; models/all/common pass no kind). Filters
88
+ * by label/id substring; a blank query returns `[]`. Derived from
89
+ * `buildModelTree`, so only node-creatable models appear and new catalog entries
90
+ * flow through automatically.
91
+ */
92
+ // MODEL_CATALOG + the provider enums are static module constants, so the tree
93
+ // never changes at runtime — build it once and reuse for every search keystroke.
94
+ let _modelTree: ModelTreeLine[] | null = null
95
+ function getModelTree(): ModelTreeLine[] {
96
+ return (_modelTree ??= buildModelTree())
97
+ }
98
+
99
+ export function searchModelVariants(query: string, kind?: ModelKind): ModelTreeVariant[] {
100
+ const q = query.trim().toLowerCase()
101
+ if (!q) return []
102
+ return getModelTree()
103
+ .flatMap((l) => l.models)
104
+ .filter((m) => (!kind || m.kind === kind) && (m.label.toLowerCase().includes(q) || m.id.toLowerCase().includes(q)))
105
+ }
106
+
107
+ export function buildModelTree(): ModelTreeLine[] {
108
+ const bySeries = new Map<string, ModelTreeLine>()
109
+ for (const entry of Object.values(MODEL_CATALOG)) {
110
+ const target = modelToNodeTarget(entry.id)
111
+ if (!target || !entry.series) continue
112
+ let line = bySeries.get(entry.series)
113
+ if (!line) {
114
+ line = { series: entry.series, family: entry.family, kind: entry.kind, models: [] }
115
+ bySeries.set(entry.series, line)
116
+ }
117
+ line.models.push({ id: entry.id, label: entry.label, kind: entry.kind, ...target })
118
+ }
119
+ return [...bySeries.values()].sort((a, b) => a.series.localeCompare(b.series))
120
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Calculate the creator's monetization markup on a base credit cost.
3
+ * Returns the markup amount (not the total).
4
+ */
5
+ export function calculateMonetizationMarkup(baseCost: number, flatFee: number, percent: number): number {
6
+ if (flatFee <= 0 && percent <= 0) return 0
7
+ return flatFee + Math.ceil(baseCost * percent / 100)
8
+ }
9
+
10
+ /**
11
+ * Calculate the total cost a runner pays (base + markup).
12
+ */
13
+ export function calculateMonetizedCost(baseCost: number, flatFee: number, percent: number): number {
14
+ return baseCost + calculateMonetizationMarkup(baseCost, flatFee, percent)
15
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Multi-select helpers for parameter dimensions that allow up to N picks.
3
+ *
4
+ * A dimension's stored value can be:
5
+ * - undefined / "" / [] → no pick
6
+ * - string → single pick (back-compat with single-select fields)
7
+ * - string[] → multi pick (1..N entries)
8
+ *
9
+ * `pickIds` normalizes any of those into a clean string[] (deduped, falsy
10
+ * entries dropped). Pickers cap the array at `maxSelected` (FIFO replacement
11
+ * is the picker's responsibility, not this helper's).
12
+ *
13
+ * Multi-select dimensions today: Person.ethnicity, Mood.mood, Aesthetic.aesthetic.
14
+ */
15
+
16
+ export function pickIds(value: unknown): string[] {
17
+ if (typeof value === "string") return value ? [value] : []
18
+ if (!Array.isArray(value)) return []
19
+ const seen = new Set<string>()
20
+ const out: string[] = []
21
+ for (const v of value) {
22
+ if (typeof v !== "string" || !v || seen.has(v)) continue
23
+ seen.add(v)
24
+ out.push(v)
25
+ }
26
+ return out
27
+ }
28
+
29
+ /**
30
+ * Cap a multi-pick array at `maxSelected`, FIFO-replacing the oldest entry
31
+ * when the array is full and a new id is added. Returns a fresh array.
32
+ */
33
+ export function togglePick(
34
+ current: ReadonlyArray<string>,
35
+ id: string,
36
+ maxSelected: number,
37
+ ): string[] {
38
+ if (current.includes(id)) return current.filter((v) => v !== id)
39
+ if (current.length < maxSelected) return [...current, id]
40
+ // FIFO replace: drop oldest, append new
41
+ return [...current.slice(1), id]
42
+ }
@@ -0,0 +1,262 @@
1
+ import {
2
+ IMAGE_GEN_PROVIDERS,
3
+ IMAGE_I2I_PROVIDERS,
4
+ IMAGE_EDIT_PROVIDERS,
5
+ UPSCALE_IMAGE_PROVIDERS,
6
+ TEXT_TO_VIDEO_PROVIDERS,
7
+ IMAGE_TO_VIDEO_PROVIDERS,
8
+ VIDEO_GEN_PROVIDERS,
9
+ LIP_SYNC_PROVIDERS,
10
+ TTS_PROVIDERS,
11
+ VOICE_DESIGN_MODELS,
12
+ } from "./model-constants.js"
13
+ import { LLM_MODEL_IDS } from "./llm-models.js"
14
+
15
+ // ──────────────────────────────────────────────────────────────────────────
16
+ // Types
17
+ // ──────────────────────────────────────────────────────────────────────────
18
+
19
+ export type QualityLevel = "low" | "mid" | "high"
20
+ export type SemanticAspectRatio = "auto" | "1:1" | "4:3" | "3:4" | "16:9" | "9:16"
21
+
22
+ export const NODE_DEFAULT_TYPES = [
23
+ // Image
24
+ "generate-image",
25
+ "image-to-image",
26
+ "edit-image",
27
+ "upscale-image",
28
+ // Video
29
+ "text-to-video",
30
+ "image-to-video",
31
+ "generate-video",
32
+ // Composition
33
+ "lip-sync",
34
+ // Audio / Music
35
+ "text-to-speech",
36
+ "generate-music",
37
+ "voice-design",
38
+ // LLM-driven
39
+ "ai-writer",
40
+ "llm-chat",
41
+ "lottie-overlay",
42
+ "3d-title",
43
+ "motion-graphics",
44
+ "image-to-text",
45
+ "qa-check",
46
+ ] as const
47
+
48
+ export type NodeDefaultType = (typeof NODE_DEFAULT_TYPES)[number]
49
+
50
+ export const QUALITY_LEVELS: readonly QualityLevel[] = ["low", "mid", "high"] as const
51
+ export const SEMANTIC_ASPECT_RATIOS: readonly SemanticAspectRatio[] = [
52
+ "auto",
53
+ "1:1",
54
+ "4:3",
55
+ "3:4",
56
+ "16:9",
57
+ "9:16",
58
+ ] as const
59
+
60
+ // ──────────────────────────────────────────────────────────────────────────
61
+ // Per-node-type registry
62
+ // ──────────────────────────────────────────────────────────────────────────
63
+
64
+ /**
65
+ * Per-node-type metadata: which field on the node carries the admin-set value,
66
+ * the valid value set, and which optional dimensions apply.
67
+ *
68
+ * `field` distinguishes nodes that use `data.provider` (image/video/audio)
69
+ * from nodes that use `data.model` (LLM nodes, voice-design).
70
+ */
71
+ interface NodeTypeMeta {
72
+ field: "provider" | "model"
73
+ validValues: readonly string[]
74
+ hasQuality: boolean
75
+ hasAspectRatio: boolean
76
+ }
77
+
78
+ // Music providers per the runtime: enum currently only lists "minimax", but
79
+ // `generate-music.defaultData.provider` is "suno" with a separate `modelVersion`.
80
+ // Until that mismatch is fixed, accept both values for admin defaults.
81
+ const MUSIC_PROVIDERS_FOR_VALIDATION = ["suno", "minimax"] as const
82
+
83
+ const META: Record<NodeDefaultType, NodeTypeMeta> = {
84
+ "generate-image": { field: "provider", validValues: IMAGE_GEN_PROVIDERS, hasQuality: true, hasAspectRatio: true },
85
+ "image-to-image": { field: "provider", validValues: IMAGE_I2I_PROVIDERS, hasQuality: true, hasAspectRatio: true },
86
+ "edit-image": { field: "provider", validValues: IMAGE_EDIT_PROVIDERS, hasQuality: false, hasAspectRatio: false },
87
+ "upscale-image": { field: "provider", validValues: UPSCALE_IMAGE_PROVIDERS, hasQuality: false, hasAspectRatio: false },
88
+ "text-to-video": { field: "provider", validValues: TEXT_TO_VIDEO_PROVIDERS, hasQuality: true, hasAspectRatio: true },
89
+ "image-to-video": { field: "provider", validValues: IMAGE_TO_VIDEO_PROVIDERS, hasQuality: true, hasAspectRatio: true },
90
+ "generate-video": { field: "provider", validValues: VIDEO_GEN_PROVIDERS, hasQuality: true, hasAspectRatio: true },
91
+ "lip-sync": { field: "provider", validValues: LIP_SYNC_PROVIDERS, hasQuality: false, hasAspectRatio: false },
92
+ "text-to-speech": { field: "provider", validValues: TTS_PROVIDERS, hasQuality: false, hasAspectRatio: false },
93
+ "generate-music": { field: "provider", validValues: MUSIC_PROVIDERS_FOR_VALIDATION, hasQuality: false, hasAspectRatio: false },
94
+ "voice-design": { field: "model", validValues: VOICE_DESIGN_MODELS, hasQuality: false, hasAspectRatio: false },
95
+ "ai-writer": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
96
+ "llm-chat": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
97
+ "lottie-overlay": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
98
+ "3d-title": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
99
+ "motion-graphics": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
100
+ "image-to-text": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
101
+ "qa-check": { field: "model", validValues: LLM_MODEL_IDS, hasQuality: false, hasAspectRatio: false },
102
+ }
103
+
104
+ export function getTargetField(nodeType: NodeDefaultType): "provider" | "model" {
105
+ return META[nodeType].field
106
+ }
107
+
108
+ export function getValidValues(nodeType: NodeDefaultType): readonly string[] {
109
+ return META[nodeType].validValues
110
+ }
111
+
112
+ export function supportedDefaultDimensions(nodeType: NodeDefaultType): {
113
+ quality: boolean
114
+ aspectRatio: boolean
115
+ } {
116
+ const m = META[nodeType]
117
+ return { quality: m.hasQuality, aspectRatio: m.hasAspectRatio }
118
+ }
119
+
120
+ export function validateProviderForNodeType(
121
+ nodeType: NodeDefaultType,
122
+ value: string,
123
+ ): string | null {
124
+ const valid = META[nodeType].validValues
125
+ if (!valid.includes(value)) {
126
+ return `value "${value}" is not valid for node type "${nodeType}"`
127
+ }
128
+ return null
129
+ }
130
+
131
+ // ──────────────────────────────────────────────────────────────────────────
132
+ // Semantic mappings — quality + aspect ratio per provider
133
+ // ──────────────────────────────────────────────────────────────────────────
134
+
135
+ /**
136
+ * Each provider stores its quality lever on a different field of node data:
137
+ * - `resolution` (1K/2K/4K, 720p/1080p, …) — most image + video providers
138
+ * - `quality` (medium/high, basic/high) — gpt-image, seedream
139
+ *
140
+ * Mapping a semantic level (low/mid/high) to a concrete value is meaningless
141
+ * without knowing WHICH field it belongs to, because writing "medium" into
142
+ * `resolution` (or "2K" into `quality`) trips the route's Zod enum at
143
+ * generate-time. Each entry pairs the field with the per-level values built
144
+ * from frontend/src/components/editor/config-panels/model-options.ts.
145
+ *
146
+ * Providers absent from this table return `undefined` from `mapQuality`,
147
+ * letting the caller fall back to the factory default value.
148
+ *
149
+ * When a provider has fewer than 3 levels, semantic levels collapse onto
150
+ * the closest concrete value (e.g. gpt-image only has medium/high → low maps
151
+ * to medium).
152
+ */
153
+ export type QualityField = "resolution" | "quality"
154
+
155
+ interface QualityMapping {
156
+ field: QualityField
157
+ values: Partial<Record<QualityLevel, string>>
158
+ }
159
+
160
+ const QUALITY_MAP: Record<string, QualityMapping> = {
161
+ // Image gen — resolution-style (1K/2K/4K)
162
+ "nano-banana-pro": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
163
+ "nano-banana-2": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
164
+ "flux": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
165
+ "flux-flex": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
166
+ "flux-i2i": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
167
+ "flux-pro-i2i": { field: "resolution", values: { low: "1K", mid: "2K", high: "2K" } },
168
+ "gpt-image-2": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
169
+ "gpt-image-2-i2i": { field: "resolution", values: { low: "1K", mid: "2K", high: "4K" } },
170
+ // Image gen — quality-style (medium/high or basic/high)
171
+ "gpt-image": { field: "quality", values: { low: "medium", mid: "medium", high: "high" } },
172
+ "gpt-image-i2i": { field: "quality", values: { low: "medium", mid: "medium", high: "high" } },
173
+ "seedream": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
174
+ "seedream-edit": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
175
+ "seedream-5-lite": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
176
+ "seedream-5-lite-i2i": { field: "quality", values: { low: "basic", mid: "basic", high: "high" } },
177
+ // Video gen — resolution-style (720p/1080p)
178
+ "veo3": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
179
+ "veo3.1": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
180
+ "kling": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
181
+ "kling-3.0": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
182
+ "seedance-2": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
183
+ "seedance-2-fast": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
184
+ "seedance-2-mini": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
185
+ "wan-2.7-i2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
186
+ "wan-2.7-t2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
187
+ "happyhorse": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
188
+ "happyhorse-i2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
189
+ "happyhorse-ref2v": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
190
+ "happyhorse-edit": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
191
+ "kling-3-omni": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
192
+ "wan-videoedit": { field: "resolution", values: { low: "720p", mid: "1080p", high: "1080p" } },
193
+ // Lightricks LTX 2.3 — 1080p / 2k / 4k (lowercase, matching VIDEO_RESOLUTION_OPTIONS).
194
+ // `field: "resolution"` is mandatory — see Provider Enum Sync pitfall 4.
195
+ "ltx-2.3-pro": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
196
+ "ltx-2.3-fast": { field: "resolution", values: { low: "1080p", mid: "2k", high: "4k" } },
197
+ "gemini-omni-video": { field: "resolution", values: { low: "720p", mid: "1080p", high: "4k" } },
198
+ // Grok Imagine Video 1.5 — only 480p/720p (no 1080p tier); high clamps to 720p.
199
+ "grok-imagine-video-1.5": { field: "resolution", values: { low: "480p", mid: "720p", high: "720p" } },
200
+ // Replicate Flux 2 family — MP-based resolution (matching IMAGE_RESOLUTION_OPTIONS["flux-2-*"]).
201
+ // `field: "resolution"` is mandatory — see Provider Enum Sync pitfall 4.
202
+ // mid = provider default: 1 MP for Klein, 2 MP for Pro/Max.
203
+ "flux-2-klein": { field: "resolution", values: { low: "0.5 MP", mid: "1 MP", high: "2 MP" } },
204
+ "flux-2-pro": { field: "resolution", values: { low: "1 MP", mid: "2 MP", high: "4 MP" } },
205
+ "flux-2-max": { field: "resolution", values: { low: "1 MP", mid: "2 MP", high: "4 MP" } },
206
+ }
207
+
208
+ const ASPECT_PASSTHROUGH_PROVIDERS = new Set([
209
+ ...IMAGE_GEN_PROVIDERS,
210
+ ...IMAGE_I2I_PROVIDERS,
211
+ ...TEXT_TO_VIDEO_PROVIDERS,
212
+ ...IMAGE_TO_VIDEO_PROVIDERS,
213
+ ])
214
+
215
+ export interface MappedQuality {
216
+ field: QualityField
217
+ value: string
218
+ }
219
+
220
+ export function mapQuality(provider: string, level: QualityLevel): MappedQuality | undefined {
221
+ const m = QUALITY_MAP[provider]
222
+ const value = m?.values[level]
223
+ return value === undefined ? undefined : { field: m!.field, value }
224
+ }
225
+
226
+ export function mapAspectRatio(
227
+ provider: string,
228
+ ratio: SemanticAspectRatio,
229
+ ): string | undefined {
230
+ if (ratio === "auto") return undefined
231
+ if (!ASPECT_PASSTHROUGH_PROVIDERS.has(provider as never)) return ratio
232
+ return ratio
233
+ }
234
+
235
+ // ──────────────────────────────────────────────────────────────────────────
236
+ // Linked field derivation
237
+ // ──────────────────────────────────────────────────────────────────────────
238
+
239
+ /**
240
+ * When admin sets `provider` for a node that has linked fields (e.g.
241
+ * generate-image stores both `provider` AND `model`), derive the linked
242
+ * fields so the resolver writes a coherent snapshot.
243
+ *
244
+ * For unmapped providers, returns `{}` — the runtime config panel applies
245
+ * its own defaulting when needed.
246
+ */
247
+ const GENERATE_IMAGE_PROVIDER_TO_MODEL: Record<string, string> = {
248
+ "nano-banana": "gemini-2.5-flash-image",
249
+ "nano-banana-pro": "gemini-2.5-flash-image",
250
+ "nano-banana-2": "gemini-2.5-flash-image",
251
+ }
252
+
253
+ export function deriveLinkedFields(
254
+ nodeType: NodeDefaultType,
255
+ value: string,
256
+ ): Record<string, unknown> {
257
+ if (nodeType === "generate-image") {
258
+ const model = GENERATE_IMAGE_PROVIDER_TO_MODEL[value]
259
+ return model ? { model } : {}
260
+ }
261
+ return {}
262
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Per-node-type list of field names eligible for fieldMappings resolution.
3
+ * Text fields also participate in {} injection when the resolver sees a
4
+ * string value containing {} markers; non-text fields just receive the
5
+ * mapped source's value verbatim.
6
+ */
7
+ export const NODE_MAPPABLE_FIELDS: Readonly<Record<string, readonly string[]>> = {
8
+ "generate-image": ["prompt", "style", "negativePrompt"],
9
+ "edit-image": ["prompt", "style", "negativePrompt"],
10
+ "image-to-image": ["prompt", "style", "negativePrompt"],
11
+ "modify-image": ["prompt", "style", "negativePrompt"],
12
+ "text-to-video": ["prompt", "negativePrompt"],
13
+ "image-to-video": ["prompt"],
14
+ // Unified t2v/i2v node — replaced the two deprecated keys above (kept only
15
+ // for back-compat with un-migrated workflow JSON). Mirrors text-to-video so
16
+ // fieldMappings/{} injection AND missing-ref detection work on the live node.
17
+ "generate-video": ["prompt", "negativePrompt"],
18
+ "video-analysis": ["analysisFocus", "youtubeUrl"],
19
+ "video-to-video": ["prompt"],
20
+ "text-to-speech": ["directText"],
21
+ "lip-sync": ["prompt"],
22
+ "generate-music": ["prompt", "lyrics", "genre", "mood"],
23
+ "text-to-audio": ["prompt"],
24
+ "suno-generate": ["prompt", "lyrics", "style", "title", "negativeStyle"],
25
+ "suno-cover": ["prompt", "lyrics", "style", "title", "negativeStyle"],
26
+ "suno-extend": ["prompt", "style", "title"],
27
+ "suno-lyrics": ["prompt"],
28
+ "suno-replace-section":["prompt", "tags", "title"],
29
+ "suno-style-boost": ["content"],
30
+ "suno-upload-extend": ["prompt", "style", "title"],
31
+ "suno-mashup": ["style", "title", "negativeStyle"],
32
+ "voice-remix": ["voiceDescription", "text"],
33
+ "voice-design": ["voiceDescription", "text"],
34
+ "forced-alignment": ["transcript"],
35
+ "ai-writer": ["systemPrompt", "userInput"],
36
+ "llm-chat": ["systemPrompt", "userInput"],
37
+ "video-composer": ["compositionPrompt"],
38
+ "after-effects": ["effectPrompt"],
39
+ "lottie-overlay": ["overlayPrompt"],
40
+ "3d-title": ["titlePrompt"],
41
+ "motion-graphics": ["motionPrompt"],
42
+ "generate-script": ["styleGuide"],
43
+ "speech-to-video": ["prompt", "negativePrompt"],
44
+ "extend-video": ["prompt"],
45
+ "motion-transfer": ["prompt"],
46
+ "cinematic-avatar": ["prompt"],
47
+ "image-to-text": ["customPrompt"],
48
+ "instagram-post": ["caption", "title"],
49
+ "tiktok-post": ["caption", "title"],
50
+ "youtube-upload": ["caption", "title"],
51
+ "linkedin-post": ["caption", "title"],
52
+ "x-post": ["caption", "title"],
53
+ "facebook-post": ["caption", "title"],
54
+ "telegram-post": ["caption", "title"],
55
+ "save-to-storage": ["filename"],
56
+ "webhook-output": ["url"],
57
+ "character": ["characterName", "description", "baseOutfit"],
58
+ "face": ["faceName", "description"],
59
+ "object": ["objectName", "description"],
60
+ "creature": ["creatureName", "description"],
61
+ "location": ["locationName", "description"],
62
+ "web-scrape": ["query", "url", "target"],
63
+ }
64
+
65
+ /** suno-generate secondary text fields exposed as `field-<key>` canvas handles. */
66
+ export const SUNO_FIELD_HANDLE_FIELDS = ["style", "lyrics", "title", "negativeStyle"] as const
67
+ /** Map a `field-<key>` handle id to its data key, or null if not a field handle. */
68
+ export function fieldKeyFromHandle(handleId: string): string | null {
69
+ return handleId.startsWith("field-") ? handleId.slice("field-".length) : null
70
+ }
@@ -0,0 +1,56 @@
1
+ import { z } from "zod"
2
+ import { extractPresetData } from "./node-preset-extract.js"
3
+
4
+ export const NODE_PRESET_EXPORT_KIND = "nodaro.node-presets" as const
5
+
6
+ export interface ExportedPreset {
7
+ nodeType: string
8
+ name: string
9
+ description?: string
10
+ data: Record<string, unknown>
11
+ }
12
+
13
+ export interface NodePresetExport {
14
+ kind: typeof NODE_PRESET_EXPORT_KIND
15
+ version: 1
16
+ exportedAt: string
17
+ presets: ExportedPreset[]
18
+ }
19
+
20
+ const exportedPresetSchema = z.object({
21
+ nodeType: z.string().min(1).max(120),
22
+ name: z.string().min(1).max(120),
23
+ description: z.string().max(500).optional(),
24
+ data: z.record(z.string(), z.unknown()),
25
+ })
26
+
27
+ const envelopeSchema = z.object({
28
+ kind: z.literal(NODE_PRESET_EXPORT_KIND),
29
+ version: z.literal(1),
30
+ exportedAt: z.string().optional().default(""),
31
+ presets: z.array(exportedPresetSchema).max(500),
32
+ })
33
+
34
+ export function buildNodePresetExport(
35
+ presets: ExportedPreset[],
36
+ exportedAtIso: string,
37
+ ): NodePresetExport {
38
+ return {
39
+ kind: NODE_PRESET_EXPORT_KIND,
40
+ version: 1,
41
+ exportedAt: exportedAtIso,
42
+ presets: presets.map((p) => ({ ...p, data: extractPresetData(p.data) })),
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Validate an unknown parsed-JSON value as a preset export; throws on invalid. Defensively
48
+ * re-strips runtime keys from each preset's data.
49
+ */
50
+ export function parseNodePresetExport(input: unknown): NodePresetExport {
51
+ const parsed = envelopeSchema.parse(input)
52
+ return {
53
+ ...parsed,
54
+ presets: parsed.presets.map((p) => ({ ...p, data: extractPresetData(p.data) })),
55
+ }
56
+ }