@@ -13,6 +13,8 @@ const MANIFEST: RegistryManifest = {
1313 homepage : "https://example.com" ,
1414 items : [
1515 { name : "my-block" , type : "hyperframes:block" } ,
16+ { name : "deprecated-block" , type : "hyperframes:block" } ,
17+ { name : "future-block" , type : "hyperframes:block" } ,
1618 { name : "my-component" , type : "hyperframes:component" } ,
1719 { name : "my-example" , type : "hyperframes:example" } ,
1820 ] ,
@@ -60,6 +62,34 @@ const COMPONENT_ITEM: RegistryItem = {
6062 ] ,
6163} ;
6264
65+ const DEPRECATED_BLOCK_ITEM : RegistryItem = {
66+ ...BLOCK_ITEM ,
67+ name : "deprecated-block" ,
68+ title : "Deprecated Block" ,
69+ deprecated : "Use `my-block` instead." ,
70+ files : [
71+ {
72+ path : "deprecated-block.html" ,
73+ target : "compositions/deprecated-block.html" ,
74+ type : "hyperframes:composition" ,
75+ } ,
76+ ] ,
77+ } ;
78+
79+ const FUTURE_BLOCK_ITEM : RegistryItem = {
80+ ...BLOCK_ITEM ,
81+ name : "future-block" ,
82+ title : "Future Block" ,
83+ minCliVersion : "999.0.0" ,
84+ files : [
85+ {
86+ path : "future-block.html" ,
87+ target : "compositions/future-block.html" ,
88+ type : "hyperframes:composition" ,
89+ } ,
90+ ] ,
91+ } ;
92+
6393const EXAMPLE_ITEM : RegistryItem = {
6494 $schema : "https://hyperframes.heygen.com/schema/registry-item.json" ,
6595 name : "my-example" ,
@@ -73,6 +103,8 @@ const EXAMPLE_ITEM: RegistryItem = {
73103
74104const ITEM_BY_NAME : Record < string , RegistryItem > = {
75105 "my-block" : BLOCK_ITEM ,
106+ "deprecated-block" : DEPRECATED_BLOCK_ITEM ,
107+ "future-block" : FUTURE_BLOCK_ITEM ,
76108 "my-component" : COMPONENT_ITEM ,
77109 "my-example" : EXAMPLE_ITEM ,
78110} ;
@@ -108,6 +140,27 @@ function uniqueBase(): string {
108140 return `https://test.invalid/${ crypto . randomUUID ( ) } ` ;
109141}
110142
143+ const DEFAULT_TEST_PATHS = {
144+ blocks : "compositions" ,
145+ components : "compositions/components" ,
146+ assets : "assets" ,
147+ } ;
148+
149+ function writeRegistryConfig (
150+ dir : string ,
151+ paths : typeof DEFAULT_TEST_PATHS = DEFAULT_TEST_PATHS ,
152+ ) : void {
153+ writeFileSync (
154+ join ( dir , "hyperframes.json" ) ,
155+ JSON . stringify ( {
156+ $schema : "https://hyperframes.heygen.com/schema/hyperframes.json" ,
157+ registry : uniqueBase ( ) ,
158+ paths,
159+ } ) ,
160+ "utf-8" ,
161+ ) ;
162+ }
163+
111164// ── Tests ───────────────────────────────────────────────────────────────────
112165
113166describe ( "add command pure helpers" , ( ) => {
@@ -172,19 +225,14 @@ describe("runAdd (integration, mocked registry)", () => {
172225 const dir = tmp ( ) ;
173226 try {
174227 // Write hyperframes.json so runAdd uses our unique baseUrl.
175- const baseUrl = uniqueBase ( ) ;
176- const cfg = {
177- $schema : "https://hyperframes.heygen.com/schema/hyperframes.json" ,
178- registry : baseUrl ,
179- paths : { blocks : "compositions" , components : "compositions/components" , assets : "assets" } ,
180- } ;
181- writeFileSync ( join ( dir , "hyperframes.json" ) , JSON . stringify ( cfg ) , "utf-8" ) ;
228+ writeRegistryConfig ( dir ) ;
182229
183230 const result = await runAdd ( { name : "my-block" , projectDir : dir , skipClipboard : true } ) ;
184231 expect ( result . ok ) . toBe ( true ) ;
185232 expect ( result . name ) . toBe ( "my-block" ) ;
186233 expect ( result . type ) . toBe ( "hyperframes:block" ) ;
187234 expect ( result . written ) . toHaveLength ( 1 ) ;
235+ expect ( result . warnings ) . toEqual ( [ ] ) ;
188236 expect ( existsSync ( join ( dir , "compositions/my-block.html" ) ) ) . toBe ( true ) ;
189237 const installed = readFileSync ( join ( dir , "compositions/my-block.html" ) , "utf-8" ) ;
190238 expect ( installed ) . toContain ( "<!-- hyperframes-registry-item: my-block -->" ) ;
@@ -195,16 +243,50 @@ describe("runAdd (integration, mocked registry)", () => {
195243 }
196244 } ) ;
197245
246+ it ( "returns a warning for deprecated registry items while still installing" , async ( ) => {
247+ const dir = tmp ( ) ;
248+ try {
249+ writeRegistryConfig ( dir ) ;
250+
251+ const result = await runAdd ( {
252+ name : "deprecated-block" ,
253+ projectDir : dir ,
254+ skipClipboard : true ,
255+ } ) ;
256+ expect ( result . warnings ) . toEqual ( [
257+ 'Registry item "deprecated-block" is deprecated: Use `my-block` instead.' ,
258+ ] ) ;
259+ expect ( existsSync ( join ( dir , "compositions/deprecated-block.html" ) ) ) . toBe ( true ) ;
260+ } finally {
261+ rmSync ( dir , { recursive : true , force : true } ) ;
262+ }
263+ } ) ;
264+
265+ it ( "blocks registry items that require a newer CLI before writing files" , async ( ) => {
266+ const dir = tmp ( ) ;
267+ try {
268+ writeRegistryConfig ( dir ) ;
269+
270+ await expect (
271+ runAdd ( {
272+ name : "future-block" ,
273+ projectDir : dir ,
274+ skipClipboard : true ,
275+ cliVersion : "0.6.79" ,
276+ } ) ,
277+ ) . rejects . toMatchObject ( {
278+ code : "incompatible-cli" ,
279+ } ) ;
280+ expect ( existsSync ( join ( dir , "compositions/future-block.html" ) ) ) . toBe ( false ) ;
281+ } finally {
282+ rmSync ( dir , { recursive : true , force : true } ) ;
283+ }
284+ } ) ;
285+
198286 it ( "remaps component snippet/style targets while leaving asset targets stable" , async ( ) => {
199287 const dir = tmp ( ) ;
200288 try {
201- const baseUrl = uniqueBase ( ) ;
202- const cfg = {
203- $schema : "https://hyperframes.heygen.com/schema/hyperframes.json" ,
204- registry : baseUrl ,
205- paths : { blocks : "compositions" , components : "src/fx" , assets : "assets" } ,
206- } ;
207- writeFileSync ( join ( dir , "hyperframes.json" ) , JSON . stringify ( cfg ) , "utf-8" ) ;
289+ writeRegistryConfig ( dir , { blocks : "compositions" , components : "src/fx" , assets : "assets" } ) ;
208290
209291 const result = await runAdd ( {
210292 name : "my-component" ,
@@ -224,19 +306,7 @@ describe("runAdd (integration, mocked registry)", () => {
224306 it ( "throws AddError with code 'example-type' when asked to add an example" , async ( ) => {
225307 const dir = tmp ( ) ;
226308 try {
227- const baseUrl = uniqueBase ( ) ;
228- writeFileSync (
229- join ( dir , "hyperframes.json" ) ,
230- JSON . stringify ( {
231- registry : baseUrl ,
232- paths : {
233- blocks : "compositions" ,
234- components : "compositions/components" ,
235- assets : "assets" ,
236- } ,
237- } ) ,
238- "utf-8" ,
239- ) ;
309+ writeRegistryConfig ( dir ) ;
240310
241311 await expect (
242312 runAdd ( { name : "my-example" , projectDir : dir , skipClipboard : true } ) ,
@@ -251,19 +321,7 @@ describe("runAdd (integration, mocked registry)", () => {
251321 it ( "throws AddError with code 'unknown-item' for a missing name" , async ( ) => {
252322 const dir = tmp ( ) ;
253323 try {
254- const baseUrl = uniqueBase ( ) ;
255- writeFileSync (
256- join ( dir , "hyperframes.json" ) ,
257- JSON . stringify ( {
258- registry : baseUrl ,
259- paths : {
260- blocks : "compositions" ,
261- components : "compositions/components" ,
262- assets : "assets" ,
263- } ,
264- } ) ,
265- "utf-8" ,
266- ) ;
324+ writeRegistryConfig ( dir ) ;
267325
268326 await expect (
269327 runAdd ( { name : "nope" , projectDir : dir , skipClipboard : true } ) ,
0 commit comments