Skip to content

Commit 3c470e2

Browse files
authored
fix: if json variable, use stringified value for reco (#551)
1 parent 45a1365 commit 3c470e2

File tree

2 files changed

+241
-189
lines changed

2 files changed

+241
-189
lines changed

src/commands/generate/types.ts

Lines changed: 43 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -12,64 +12,19 @@ import {
1212
fetchFeatures,
1313
} from '../../api/features'
1414
import { fetchCustomProperties } from '../../api/customProperties'
15-
16-
const reactImports = (oldRepos: boolean, strictCustomData: boolean) => {
17-
if (oldRepos) {
18-
return `import { DVCVariable, DVCVariableValue } from '@devcycle/devcycle-js-sdk'
1915
import {
20-
useVariable as originalUseVariable,
21-
useVariableValue as originalUseVariableValue
22-
} from '@devcycle/devcycle-react-sdk'
23-
24-
export type DevCycleJSON = { [key: string]: string | boolean | number }
25-
26-
`
27-
} else {
28-
return `import {
29-
useVariable as originalUseVariable,
30-
useVariableValue as originalUseVariableValue,
31-
DVCVariable,
32-
DVCVariableValue,${!strictCustomData ? '\n DVCCustomDataJSON,' : ''}
33-
DevCycleJSON
34-
} from '@devcycle/react-client-sdk'
35-
36-
`
37-
}
38-
}
39-
40-
const nextImports = (strictCustomData: boolean) => {
41-
return `import {
42-
useVariable as originalUseVariable,
43-
useVariableValue as originalUseVariableValue,
44-
DVCVariable,
45-
DVCVariableValue,${!strictCustomData ? '\n DVCCustomDataJSON,' : ''}
46-
DevCycleJSON
47-
} from '@devcycle/nextjs-sdk'
48-
49-
`
50-
}
51-
52-
const reactOverrides = `
53-
export type UseVariableValue = <
54-
K extends string & keyof DVCVariableTypes
55-
>(
56-
key: K,
57-
defaultValue: DVCVariableTypes[K]
58-
) => DVCVariableTypes[K]
59-
60-
export const useVariableValue = originalUseVariableValue as UseVariableValue
61-
62-
export type UseVariable = <
63-
K extends string & keyof DVCVariableTypes,
64-
T extends DVCVariableValue & DVCVariableTypes[K],
65-
>(
66-
key: K,
67-
defaultValue: DVCVariableTypes[K]
68-
) => DVCVariable<T>
69-
70-
export const useVariable = originalUseVariable as UseVariable
71-
72-
`
16+
blockComment,
17+
findCreatorName,
18+
generateCustomDataType,
19+
getRecommendedValueForStale,
20+
getVariableType,
21+
isVariableDeprecated,
22+
isVariableStale,
23+
nextImports,
24+
reactImports,
25+
reactOverrides,
26+
sanitizeDescription,
27+
} from '../../utils/types'
7328

7429
export default class GenerateTypes extends Base {
7530
static hidden = false
@@ -324,8 +279,38 @@ export default class GenerateTypes extends Base {
324279
variable,
325280
staleInfo.feature as Feature,
326281
)
282+
283+
const formatRecommendedValueForComment = (
284+
recommendedValue: string,
285+
) => {
286+
if (recommendedValue) {
287+
try {
288+
const parsed = JSON.parse(recommendedValue)
289+
if (typeof parsed === 'object' && parsed !== null) {
290+
const indentation = indent ? ' ' : ''
291+
const jsonString = JSON.stringify(parsed, null, 4)
292+
return (
293+
'\n' +
294+
jsonString
295+
.split('\n')
296+
.map((line) =>
297+
line ? indentation + line : line,
298+
)
299+
.join('\n') +
300+
'\n'
301+
)
302+
}
303+
} catch {
304+
return recommendedValue
305+
}
306+
}
307+
return recommendedValue
308+
}
309+
310+
const formattedRecommendedValue =
311+
formatRecommendedValueForComment(recommendedValue)
327312
staleWarning = staleInfo.stale
328-
? `@stale This variable is part of "${staleInfo.feature?.name}" feature with stale reason: ${staleInfo.feature?.staleness?.reason}. ${recommendedValue ? `Recommended value to set it to: ${recommendedValue}` : ''}\n`
313+
? `@stale This variable is part of "${staleInfo.feature?.name}" feature with stale reason: ${staleInfo.feature?.staleness?.reason}. ${recommendedValue ? `Recommended value to set it to: ${formattedRecommendedValue}` : ''}\n`
329314
: ''
330315
}
331316

@@ -392,134 +377,3 @@ export const ${constantName} = '${hashedKey}' as const`
392377
}
393378
}
394379
}
395-
396-
export function sanitizeDescription(description: string) {
397-
// Remove newlines, tabs, and carriage returns for proper display
398-
return description.replace(/[\r\n\t]/g, ' ').trim()
399-
}
400-
401-
export function findCreatorName(
402-
orgMembers: OrganizationMember[],
403-
creatorId: string,
404-
) {
405-
return (
406-
orgMembers.find((member) => member.user_id === creatorId)?.name ||
407-
'Unknown User'
408-
)
409-
}
410-
411-
export const blockComment = (
412-
description: string,
413-
creator: string,
414-
createdDate: string,
415-
indent: boolean,
416-
key?: string,
417-
deprecationWarning?: string,
418-
staleWarning?: string,
419-
) => {
420-
const indentString = indent ? ' ' : ''
421-
return (
422-
indentString +
423-
'/**\n' +
424-
(key ? `${indentString} * key: ${key}\n` : '') +
425-
(description !== ''
426-
? `${indentString} * description: ${description}\n`
427-
: '') +
428-
`${indentString} * created by: ${creator}\n` +
429-
`${indentString} * created on: ${createdDate}\n` +
430-
(deprecationWarning
431-
? `${indentString} * ${deprecationWarning}\n`
432-
: '') +
433-
(staleWarning ? `${indentString} * ${staleWarning}\n` : '') +
434-
indentString +
435-
'*/'
436-
)
437-
}
438-
439-
export function getVariableType(variable: Variable) {
440-
if (
441-
variable.validationSchema &&
442-
variable.validationSchema.schemaType === 'enum'
443-
) {
444-
// TODO fix the schema so it doesn't think enumValues is an object
445-
const enumValues = variable.validationSchema.enumValues as
446-
| string[]
447-
| number[]
448-
if (enumValues === undefined || enumValues.length === 0) {
449-
return variable.type.toLocaleLowerCase()
450-
}
451-
return enumValues.map((value) => `'${value}'`).join(' | ')
452-
}
453-
if (variable.type === 'JSON') {
454-
return 'DevCycleJSON'
455-
}
456-
return variable.type.toLocaleLowerCase()
457-
}
458-
459-
function isVariableDeprecated(variable: Variable, features: Feature[]) {
460-
if (!variable._feature || variable.persistent) return { deprecated: false }
461-
const feature = features.find((f) => f._id === variable._feature)
462-
return { deprecated: feature && feature.status !== 'active', feature }
463-
}
464-
465-
function isVariableStale(variable: Variable, features: Feature[]) {
466-
if (!variable._feature || variable.persistent) return { stale: false }
467-
const feature = features.find((f) => f._id === variable._feature)
468-
return { stale: feature && feature.staleness, feature }
469-
}
470-
471-
function getRecommendedValueForStale(variable: Variable, feature: Feature) {
472-
if (!feature) {
473-
return variable.defaultValue
474-
}
475-
const reason = feature.staleness?.reason
476-
if (reason === 'unused') {
477-
return variable.defaultValue
478-
} else if (reason === 'released') {
479-
if (feature.staleness?.metaData?.releaseVariation) {
480-
const stalenessMetaData = feature.staleness?.metaData
481-
?.releaseVariation as {
482-
_variation: string
483-
variationKey: string
484-
variationName: string
485-
}
486-
const releaseVariation = feature.variations?.find(
487-
(v) => v._id === stalenessMetaData._variation,
488-
)
489-
return (
490-
releaseVariation?.variables?.[variable.key] ||
491-
variable.defaultValue
492-
)
493-
}
494-
}
495-
return variable.defaultValue
496-
}
497-
498-
const generateCustomDataType = (
499-
customProperties: CustomProperty[],
500-
strict: boolean,
501-
) => {
502-
const properties = customProperties
503-
.map((prop) => {
504-
const propType = prop.type.toLowerCase()
505-
const schema = prop.schema?.enumSchema
506-
const isRequired = prop.schema?.required ?? false
507-
const optionalMarker = isRequired ? '' : '?'
508-
if (schema) {
509-
const enumValues = schema.allowedValues
510-
.map(({ label, value }) => {
511-
const valueStr =
512-
typeof value === 'number' ? value : `'${value}'`
513-
return ` // ${label}\n ${valueStr}`
514-
})
515-
.join(' | \n')
516-
return ` '${prop.propertyKey}'${optionalMarker}: | \n${enumValues}${schema.allowAdditionalValues ? ` |\n ${propType}` : ''}`
517-
}
518-
return ` '${prop.propertyKey}'${optionalMarker}: ${propType}`
519-
})
520-
.join('\n')
521-
522-
return `export type CustomData = {
523-
${properties}
524-
}${!strict ? ' & DVCCustomDataJSON' : ''}\n`
525-
}

0 commit comments

Comments
 (0)