Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions src/utils/init-script-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,23 @@ export const InitScriptSchemaVersions = z.object({
solana: z.string().optional(),
})

export const InitScriptSchemaRename = z.record(
z.object({
// TODO: Rename 'paths' to 'in' (breaking change)
paths: z.array(z.string()),
to: z.string(),
}),
)
const InitScriptSchemaRenameEntryBase = z.object({
// Accept alias `in` for backward/forward compatibility and normalize to `paths`
in: z.array(z.string()).optional(),
paths: z.array(z.string()).optional(),
to: z.string(),
})

export const InitScriptSchemaRename = z.record(InitScriptSchemaRenameEntryBase).transform((input) => {
// Normalize entries: if `in` is provided, move to `paths`
const normalized: Record<string, { paths: string[]; to: string }> = {}
for (const key of Object.keys(input)) {
const entry = input[key] as { in?: string[]; paths?: string[]; to: string }
const paths = entry.paths ?? entry.in ?? []
normalized[key] = { paths, to: entry.to }
}
return normalized
})

export const InitScriptSchema = z.object({
instructions: InitScriptSchemaInstructions.optional(),
Expand Down
46 changes: 46 additions & 0 deletions test/init-script-schema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { describe, expect, it } from 'vitest'
import { InitScriptSchema } from '../src/utils/init-script-schema'

describe('InitScriptSchema - rename alias', () => {
const parseRename = (rename: unknown) => InitScriptSchema.parse({ rename }).rename

it('should accept `in` alias and normalize to `paths`', () => {
const parsed = parseRename({ example: { in: ['some/path/to/file'], to: '{{name}}Example' } } as unknown)

// @ts-expect-error normalized by schema transform
expect(parsed.example.in).toBeUndefined()
expect(parsed?.example.paths).toEqual(['some/path/to/file'])
expect(parsed?.example.to).toBe('{{name}}Example')
})

it('should accept `paths` field without changes', () => {
const parsed = parseRename({ example: { paths: ['some/path/to/file'], to: '{{name}}Example' } })

expect(parsed?.example.paths).toEqual(['some/path/to/file'])
expect(parsed?.example.to).toBe('{{name}}Example')
})

it('should prioritize `paths` over `in` when both provided', () => {
const entry = { in: ['path/from/in'], paths: ['path/from/paths'], to: '{{name}}Example' } as unknown
const parsed = parseRename({ example: entry })

expect(parsed?.example.paths).toEqual(['path/from/paths'])
})

it('should handle empty arrays', () => {
const parsed = parseRename({ example: { in: [], to: '{{name}}Example' } } as unknown)

expect(parsed?.example.paths).toEqual([])
})

it('should handle mixed `in` and `paths` usage', () => {
const rename = {
example1: { in: ['some/path/to/file1'], to: '{{name}}Example1' },
example2: { paths: ['some/path/to/file2'], to: '{{name}}Example2' },
} as unknown
const parsed = parseRename(rename)

expect(parsed?.example1.paths).toEqual(['some/path/to/file1'])
expect(parsed?.example2.paths).toEqual(['some/path/to/file2'])
})
})
2 changes: 1 addition & 1 deletion test/search-and-replace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('searchAndReplace', () => {
})

it('should handle errors gracefully', async () => {
const consoleErrorSpy = vi.spyOn(console, 'error')
const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})

// Mock the file system and simulate an error for readFile
mockFs({
Expand Down