Skip to content

Commit a2d4432

Browse files
Merge pull request #21 from Contentstack-Solutions/fix/global_field
fix: added support to create global fields type uniquely for all fields
2 parents 42520a9 + be0571d commit a2d4432

File tree

6 files changed

+103
-19
lines changed

6 files changed

+103
-19
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "contentstack-cli-tsgen",
33
"description": "Generate TypeScript typings from a Stack.",
4-
"version": "1.0.14",
4+
"version": "2.0.0",
55
"author": "Michael Davis",
66
"bugs": "https://github.com/Contentstack-Solutions/contentstack-cli-tsgen/issues",
77
"dependencies": {

src/commands/tsgen.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {Command, flags} from '@contentstack/cli-command'
2-
import {stackConnect, StackConnectionConfig} from '../lib/stack/client'
2+
import {getGlobalFields, stackConnect, StackConnectionConfig} from '../lib/stack/client'
3+
import {ContentType} from '../lib/stack/schema'
34
import tsgenRunner from '../lib/tsgen/runner'
45

56
export default class TypeScriptCodeGeneratorCommand extends Command {
@@ -69,10 +70,19 @@ export default class TypeScriptCodeGeneratorCommand extends Command {
6970
environment: token.environment || '',
7071
}
7172

72-
const client = await stackConnect(this.deliveryAPIClient.Stack, config)
73+
const [client, globalFields] = await Promise.all([stackConnect(this.deliveryAPIClient.Stack, config), getGlobalFields(config)])
7374

74-
if (client.types) {
75-
const result = await tsgenRunner(outputPath, client.types, prefix, includeDocumentation)
75+
let schemas: ContentType[] = []
76+
if (client.types?.length) {
77+
if ((globalFields as any)?.global_fields?.length) {
78+
schemas = schemas.concat((globalFields as any).global_fields as ContentType)
79+
schemas = schemas.map(schema => ({
80+
...schema,
81+
schema_type: 'global_field',
82+
}))
83+
}
84+
schemas = schemas.concat(client.types)
85+
const result = await tsgenRunner(outputPath, schemas, prefix, includeDocumentation)
7686
this.log(`Wrote ${result.definitions} Content Types to '${result.outputPath}'.`)
7787
} else {
7888
this.log('No Content Types exist in the Stack.')

src/lib/stack/client.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
import * as http from 'https'
2+
3+
type RegionUrlMap = {
4+
[prop: string]: string;
5+
};
6+
7+
const REGION_URL_MAPPING: RegionUrlMap = {
8+
na: 'cdn.contentstack.io',
9+
us: 'cdn.contentstack.io',
10+
eu: 'eu-cdn.contentstack.com',
11+
'azure-na': 'azure-na-cdn.contentstack.com',
12+
}
13+
114
export type StackConnectionConfig = {
215
apiKey: string;
316
token: string;
@@ -34,3 +47,41 @@ export async function stackConnect(client: any, config: StackConnectionConfig) {
3447
)
3548
}
3649
}
50+
51+
// Currently delivery sdk does not support querying global fields on a stack. Hence direct call is required.
52+
export async function getGlobalFields(config: StackConnectionConfig) {
53+
try {
54+
return new Promise((resolve, reject) => {
55+
const options: any = {
56+
host: (REGION_URL_MAPPING as any)[config.region],
57+
path: 'v3/global_fields?include_branch=false',
58+
port: 443,
59+
method: 'GET',
60+
headers: {
61+
api_key: config.apiKey,
62+
access_token: config.token,
63+
},
64+
}
65+
const req = http.request(options, res => {
66+
res.setEncoding('utf8')
67+
let body = ''
68+
res.on('data', chunk => {
69+
body += chunk
70+
})
71+
res.on('end', () => {
72+
if (res.statusCode === 200) {
73+
resolve(JSON.parse(body))
74+
} else {
75+
reject(body)
76+
}
77+
})
78+
})
79+
req.on('error', error => {
80+
reject(error)
81+
})
82+
req.end()
83+
})
84+
} catch (error) {
85+
throw new Error('Could not connect to the stack. Please check your credentials.')
86+
}
87+
}

src/lib/stack/schema.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export type FieldOptions = {
2121
export type Block = {
2222
title: string;
2323
schema: Schema;
24+
reference_to?: string;
2425
} & Identifier;
2526

2627
export type GlobalField = {
@@ -55,4 +56,7 @@ export type ContentType = {
5556
description: string;
5657
schema: Schema;
5758
_version: number;
59+
reference_to?: string;
60+
data_type?: string;
61+
schema_type?: string;
5862
} & Identifier;

src/lib/tsgen/factory.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,11 @@ export default function (userOptions: TSGenOptions) {
8989
if (flag === TypeFlags.BuiltinJS) {
9090
visitedJSTypes.add(type)
9191
} else if (flag === TypeFlags.UserGlobalField) {
92-
visitedGlobalFields.add(type)
92+
const _type = name_type(field.reference_to)
93+
visitedGlobalFields.add(_type)
9394

94-
if (!cachedGlobalFields[type]) {
95-
cachedGlobalFields[type] = {
95+
if (!cachedGlobalFields[_type]) {
96+
cachedGlobalFields[_type] = {
9697
definition: visit_content_type(field),
9798
}
9899
}
@@ -116,7 +117,7 @@ export default function (userOptions: TSGenOptions) {
116117
function define_interface(
117118
contentType: ContentstackTypes.ContentType | ContentstackTypes.GlobalField
118119
) {
119-
return ['export interface', name_type(contentType.uid)].join(' ')
120+
return ['export interface', name_type(contentType.data_type === 'global_field' ? (contentType.reference_to as string) : contentType.uid)].join(' ')
120121
}
121122

122123
function op_array(type: string, field: ContentstackTypes.Field) {
@@ -195,9 +196,13 @@ export default function (userOptions: TSGenOptions) {
195196
}
196197

197198
function visit_field(field: ContentstackTypes.Field) {
199+
let fieldType = ''
200+
if (field.data_type === 'global_field' && cachedGlobalFields[name_type(field.reference_to)]) {
201+
fieldType = name_type(field.reference_to)
202+
}
198203
return [
199204
field.uid + op_required(field.mandatory) + ':',
200-
visit_field_type(field) + ';',
205+
fieldType || visit_field_type(field) + ';',
201206
].join(' ')
202207
}
203208

@@ -231,9 +236,7 @@ export default function (userOptions: TSGenOptions) {
231236
) {
232237
return (
233238
'{' +
234-
[block.uid + ':', '{' + visit_fields(block.schema || []) + '};'].join(
235-
' '
236-
) +
239+
[block.uid + ':', block.reference_to ? name_type(block.reference_to as string) + ';' : '{' + visit_fields(block.schema || []) + '};'].join(' ') +
237240
visit_block_names(field, block) +
238241
'}'
239242
)
@@ -276,7 +279,7 @@ export default function (userOptions: TSGenOptions) {
276279
)
277280
}
278281

279-
const name = name_type(field.uid)
282+
const name = name_type(field.reference_to)
280283

281284
return name
282285
}
@@ -293,7 +296,19 @@ export default function (userOptions: TSGenOptions) {
293296
return ['(', references.join(' | '), ')', '[]'].join('')
294297
}
295298

296-
return function (contentType: ContentstackTypes.ContentType): TSGenResult {
299+
return function (contentType: ContentstackTypes.ContentType): TSGenResult|any {
300+
if (contentType.schema_type === 'global_field') {
301+
const name = name_type(contentType.uid)
302+
if (!cachedGlobalFields[name]) {
303+
cachedGlobalFields[name] = {
304+
definition: visit_content_type(contentType),
305+
}
306+
}
307+
return {
308+
definition: cachedGlobalFields[name].definition,
309+
isGlobalField: true,
310+
}
311+
}
297312
return {
298313
definition: visit_content_type(contentType),
299314
metadata: {

src/lib/tsgen/runner.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,15 @@ export default async function tsgenRunner(outputFile: string, contentTypes: any[
4343
for (const contentType of contentTypes) {
4444
const tsgenResult = tsgen(contentType)
4545

46-
definitions.push(tsgenResult.definition)
46+
if (tsgenResult.isGlobalField) {
47+
globalFields.add(tsgenResult.definition)
48+
} else {
49+
definitions.push(tsgenResult.definition)
4750

48-
tsgenResult.metadata.types.globalFields.forEach((field: string) => {
49-
globalFields.add(tsgenResult.metadata.dependencies.globalFields[field].definition)
50-
})
51+
tsgenResult.metadata.types.globalFields.forEach((field: string) => {
52+
globalFields.add(tsgenResult.metadata.dependencies.globalFields[field].definition)
53+
})
54+
}
5155
}
5256

5357
const output = await format(

0 commit comments

Comments
 (0)