123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686 |
- var fs = require('fs');
- var path = require('path');
- var pruneShapes = require('./prune-shapes').pruneShapes;
- var CUSTOM_CONFIG_ENUMS = {
- DUALSTACK: {
- FILE_NAME: 'config_use_dualstack',
- INTERFACE: 'UseDualstackConfigOptions'
- }
- };
- function TSGenerator(options) {
- this._sdkRootDir = options.SdkRootDirectory || process.cwd();
- this._apiRootDir = path.join(this._sdkRootDir, 'apis');
- this._metadataPath = path.join(this._apiRootDir, 'metadata.json');
- this._clientsDir = path.join(this._sdkRootDir, 'clients');
- // Lazy loading values on usage to avoid side-effects in constructor
- this.metadata = null;
- this.typings = {};
- this.streamTypes = {};
- }
- /**
- * Loads the AWS SDK metadata.json file.
- */
- TSGenerator.prototype.loadMetadata = function loadMetadata() {
- var metadataFile = fs.readFileSync(this._metadataPath);
- this.metadata = JSON.parse(metadataFile);
- return this.metadata;
- };
- /**
- * Modifies metadata to include api model filenames.
- */
- TSGenerator.prototype.fillApiModelFileNames = function fillApiModelFileNames() {
- var modelPaths = fs.readdirSync(this._apiRootDir);
- if (!this.metadata) {
- this.loadMetadata();
- }
- var metadata = this.metadata;
- // sort paths so latest versions appear first
- modelPaths = modelPaths.sort(function sort(a, b) {
- if (a < b) {
- return 1;
- } else if (a > b) {
- return -1;
- } else {
- return 0;
- }
- });
- // Only get latest version of models
- var foundModels = Object.create(null);
- modelPaths.forEach(function(modelFileName) {
- var match = modelFileName.match(/^(.+)(-[\d]{4}-[\d]{2}-[\d]{2})\.normal\.json$/i);
- if (match) {
- var model = match[1];
- // add version
- var version = match[2].substring(1);
- if (!foundModels[model]) {
- foundModels[model] = {
- latestFileName: modelFileName,
- versions: [version]
- };
- } else {
- foundModels[model].versions.push(version);
- }
- }
- });
- // now update the metadata
- var keys = Object.keys(metadata);
- keys.forEach(function(key) {
- var modelName = metadata[key].prefix || key;
- var modelInfo = foundModels[modelName];
- metadata[key].api_path = modelInfo.latestFileName;
- // find waiters file
- var baseName = modelInfo.latestFileName.split('.')[0];
- if (modelPaths.indexOf(baseName + '.waiters2.json') >= 0) {
- metadata[key].waiters_path = baseName + '.waiters2.json';
- }
- // add versions
- if (!metadata[key].versions) {
- metadata[key].versions = [];
- }
- metadata[key].versions = [].concat(metadata[key].versions, modelInfo.versions);
- });
- };
- TSGenerator.prototype.updateDynamoDBDocumentClient = function updateDynamoDBDocumentClient() {
- // read in document client customization
- var docClientCustomCode = fs.readFileSync(path.join(this._sdkRootDir, 'lib', 'dynamodb', 'document_client.d.ts')).toString();
- var lines = docClientCustomCode.split('\n');
- var namespaceIndexStart = -1;
- var namespaceIndexEnd = -1;
- for (var i = 0, iLen = lines.length; i < iLen; i++) {
- var line = lines[i];
- // find exported namespace
- if (line.indexOf('//<!--auto-generated start-->') >= 0) {
- namespaceIndexStart = i;
- }
- if (line.indexOf('//<!--auto-generated end-->') >= 0) {
- namespaceIndexEnd = i;
- break;
- }
- }
- if (namespaceIndexStart >= 0 && namespaceIndexEnd >= 0) {
- // insert doc client interfaces
- lines.splice(namespaceIndexStart + 1, (namespaceIndexEnd - namespaceIndexStart - 1), this.generateDocumentClientInterfaces(1));
- var code = lines.join('\n');
- this.writeTypingsFile('document_client', path.join(this._sdkRootDir, 'lib', 'dynamodb'), code);
- }
- };
- /**
- * Generates the file containing DocumentClient interfaces.
- */
- TSGenerator.prototype.generateDocumentClientInterfaces = function generateDocumentClientInterfaces(tabCount) {
- tabCount = tabCount || 0;
- var self = this;
- // get the dynamodb model
- var dynamodbModel = this.loadServiceApi('dynamodb');
- var code = '';
- // stub Blob interface
- code += this.tabs(tabCount) + 'interface Blob {}\n';
- // generate shapes
- var modelShapes = dynamodbModel.shapes;
- // iterate over each shape
- var shapeKeys = Object.keys(modelShapes);
- shapeKeys.forEach(function (shapeKey) {
- var modelShape = modelShapes[shapeKey];
- // ignore exceptions
- if (modelShape.exception) {
- return;
- }
- // overwrite AttributeValue
- if (shapeKey === 'AttributeValue') {
- code += self.generateDocString('A JavaScript object or native type.', tabCount);
- code += self.tabs(tabCount) + 'export type ' + shapeKey + ' = any;\n';
- return;
- }
- code += self.generateTypingsFromShape(dynamodbModel, shapeKey, modelShape, tabCount, []);
- });
- return code;
- };
- /**
- * Returns a service model based on the serviceIdentifier.
- */
- TSGenerator.prototype.loadServiceApi = function loadServiceApi(serviceIdentifier) {
- // first, find the correct identifier
- var metadata = this.metadata;
- var serviceFilePath = path.join(this._apiRootDir, metadata[serviceIdentifier].api_path);
- var serviceModelFile = fs.readFileSync(serviceFilePath);
- var serviceModel = JSON.parse(serviceModelFile);
- // load waiters file if it exists
- var waiterFilePath;
- if (metadata[serviceIdentifier].waiters_path) {
- waiterFilePath = path.join(this._apiRootDir, metadata[serviceIdentifier].waiters_path);
- var waiterModelFile = fs.readFileSync(waiterFilePath);
- var waiterModel = JSON.parse(waiterModelFile);
- serviceModel.waiters = waiterModel.waiters;
- }
- return serviceModel;
- };
- /**
- * Determines if a member is required by checking for it in a list.
- */
- TSGenerator.prototype.checkRequired = function checkRequired(list, member) {
- if (list.indexOf(member) >= 0) {
- return true;
- }
- return false;
- };
- /**
- * Generates whitespace based on the count.
- */
- TSGenerator.prototype.tabs = function tabs(count) {
- var code = '';
- for (var i = 0; i < count; i++) {
- code += ' ';
- }
- return code;
- };
- /**
- * Transforms documentation string to a more readable format.
- */
- TSGenerator.prototype.transformDocumentation = function transformDocumentation(documentation) {
- if (!documentation) {
- return '';
- }
- documentation = documentation.replace(/<(?:.|\n)*?>/gm, '');
- documentation = documentation.replace(/\*\//g, '*');
- return documentation;
- };
- /**
- * Returns a doc string based on the supplied documentation.
- * Also tabs the doc string if a count is provided.
- */
- TSGenerator.prototype.generateDocString = function generateDocString(documentation, tabCount) {
- tabCount = tabCount || 0;
- var code = '';
- code += this.tabs(tabCount) + '/**\n';
- code += this.tabs(tabCount) + ' * ' + this.transformDocumentation(documentation) + '\n';
- code += this.tabs(tabCount) + ' */\n';
- return code;
- };
- /**
- * Returns an array of custom configuration options based on a service identiffier.
- * Custom configuration options are determined by checking the metadata.json file.
- */
- TSGenerator.prototype.generateCustomConfigFromMetadata = function generateCustomConfigFromMetadata(serviceIdentifier) {
- // some services have additional configuration options that are defined in the metadata.json file
- // i.e. dualstackAvailable = useDualstack
- // create reference to custom options
- var customConfigurations = [];
- var serviceMetadata = this.metadata[serviceIdentifier];
- // loop through metadata members
- for (var memberName in serviceMetadata) {
- if (!serviceMetadata.hasOwnProperty(memberName)) {
- continue;
- }
- // check configs
- switch (memberName) {
- case 'dualstackAvailable':
- customConfigurations.push(CUSTOM_CONFIG_ENUMS.DUALSTACK);
- break;
- }
- }
- return customConfigurations;
- };
- TSGenerator.prototype.generateSafeShapeName = function generateSafeShapeName(name, blacklist) {
- blacklist = blacklist || [];
- if (blacklist.indexOf(name) >= 0) {
- return '_' + name;
- }
- return name;
- };
- TSGenerator.prototype.extractTypesDependOnStream = function extractTypesDependOnStream(shapeKey, modelShape) {
- var streamTypeList = [];
- if (typeof modelShape !== "object" || Object.keys(modelShape).length === 0) {
- return [];
- }
- if (modelShape.streaming) {
- streamTypeList.push(shapeKey);
- return streamTypeList;
- }
- for (var subModelKey in modelShape) {
- var subModel = modelShape[subModelKey];
- var subStreamTypeList = this.extractTypesDependOnStream(subModelKey, subModel);
- if (Object.keys(subStreamTypeList).length !== 0) {
- for (var streamType of subStreamTypeList) {
- streamTypeList.push(streamType);
- }
- }
- }
- return streamTypeList;
- }
- TSGenerator.prototype.addReadableType = function addReadableType(shapeKey) {
- var code = '';
- if (this.streamTypes[shapeKey]) {
- code += '|Readable';
- } else if (shapeKey[0] === '_' && this.streamTypes[shapeKey.slice(1)]) {
- code += '|Readable';
- }
- return code;
- }
- /**
- * Generates a type or interface based on the shape.
- */
- TSGenerator.prototype.generateTypingsFromShape = function generateTypingsFromShape(model, shapeKey, shape, tabCount, customClassNames) {
- // some shapes shouldn't be generated if they are javascript primitives
- var jsPrimitives = ['string', 'boolean', 'number'];
- if (jsPrimitives.indexOf(shapeKey) >= 0) {
- return '';
- }
- if (['Date', 'Blob'].indexOf(shapeKey) >= 0) {
- shapeKey = '_' + shapeKey;
- }
- // In at least one (cloudfront.Signer) case, a class on a service namespace clashes with a shape
- shapeKey = this.generateSafeShapeName(shapeKey, customClassNames);
- var self = this;
- var code = '';
- tabCount = tabCount || 0;
- var tabs = this.tabs;
- var type = shape.type;
- if (shape.eventstream) {
- // eventstreams MUST be structures
- var members = Object.keys(shape.members);
- var events = members.map(function(member) {
- // each member is an individual event type, so each must be optional
- return member + '?:' + shape.members[member].shape;
- });
- return code += tabs(tabCount) + 'export type ' + shapeKey + ' = EventStream<{' + events.join(',') + '}>;\n';
- }
- if (type === 'structure') {
- if (shape.isDocument) {
- return code += tabs(tabCount) + 'export type ' + shapeKey + ' = DocumentType;\n'
- }
- code += tabs(tabCount) + 'export interface ' + shapeKey + ' {\n';
- var members = shape.members;
- // cycle through members
- var memberKeys = Object.keys(members);
- memberKeys.forEach(function(memberKey) {
- // docs
- var member = members[memberKey];
- if (member.documentation) {
- code += self.generateDocString(member.documentation, tabCount + 1);
- }
- var required = self.checkRequired(shape.required || [], memberKey) ? '' : '?';
- var memberType = member.shape;
- if (member.eventpayload) {
- // eventpayloads are always either structures, or buffers
- if (['blob', 'binary'].indexOf(model.shapes[memberType].type) >= 0) {
- memberType = 'Buffer';
- }
- }
- memberType = self.generateSafeShapeName(memberType, [].concat(customClassNames, ['Date', 'Blob']));
- code += tabs(tabCount + 1) + memberKey + required + ': ' + memberType + ';\n';
- });
- code += tabs(tabCount) + '}\n';
- } else if (type === 'list') {
- code += tabs(tabCount) + 'export type ' + shapeKey + ' = ' + this.generateSafeShapeName(shape.member.shape, customClassNames) + '[];\n';
- } else if (type === 'map') {
- code += tabs(tabCount) + 'export type ' + shapeKey + ' = {[key: string]: ' + this.generateSafeShapeName(shape.value.shape, customClassNames) + '};\n';
- } else if (type === 'string' || type === 'character') {
- var stringType = 'string';
- if (Array.isArray(shape.enum)) {
- stringType = shape.enum.map(function(s) {
- return '"' + s + '"';
- }).join('|') + '|' + stringType;
- }
- code += tabs(tabCount) + 'export type ' + shapeKey + ' = ' + stringType + ';\n';
- } else if (['double', 'long', 'short', 'biginteger', 'bigdecimal', 'integer', 'float'].indexOf(type) >= 0) {
- code += tabs(tabCount) + 'export type ' + shapeKey + ' = number;\n';
- } else if (type === 'timestamp') {
- code += tabs(tabCount) + 'export type ' + shapeKey + ' = Date;\n';
- } else if (type === 'boolean') {
- code += tabs(tabCount) + 'export type ' + shapeKey + ' = boolean;\n';
- } else if (type === 'blob' || type === 'binary') {
- code += tabs(tabCount) + 'export type ' + shapeKey + ' = Buffer|Uint8Array|Blob|string'
- + self.addReadableType(shapeKey)
- +';\n';
- }
- return code;
- };
- /**
- * Generates a class method type for an operation.
- */
- TSGenerator.prototype.generateTypingsFromOperations = function generateTypingsFromOperations(className, operation, operationName, tabCount) {
- var code = '';
- tabCount = tabCount || 0;
- var tabs = this.tabs;
- var input = operation.input;
- var output = operation.output;
- operationName = operationName.charAt(0).toLowerCase() + operationName.substring(1);
- var inputShape = input ? className + '.Types.' + input.shape : '{}';
- var outputShape = output ? className + '.Types.' + output.shape : '{}';
- if (input) {
- code += this.generateDocString(operation.documentation, tabCount);
- code += tabs(tabCount) + operationName + '(params: ' + inputShape + ', callback?: (err: AWSError, data: ' + outputShape + ') => void): Request<' + outputShape + ', AWSError>;\n';
- }
- code += this.generateDocString(operation.documentation, tabCount);
- code += tabs(tabCount) + operationName + '(callback?: (err: AWSError, data: ' + outputShape + ') => void): Request<' + outputShape + ', AWSError>;\n';
- return code;
- };
- TSGenerator.prototype.generateConfigurationServicePlaceholders = function generateConfigurationServicePlaceholders() {
- /**
- * Should create a config service placeholder
- */
- var self = this;
- var metadata = this.metadata;
- // Iterate over every service
- var serviceIdentifiers = Object.keys(metadata);
- var code = '';
- var configCode = '';
- var versionsCode = '';
- code += 'import * as AWS from \'../clients/all\';\n';
- configCode += 'export abstract class ConfigurationServicePlaceholders {\n';
- versionsCode += 'export interface ConfigurationServiceApiVersions {\n';
- serviceIdentifiers.forEach(function(serviceIdentifier) {
- var className = self.metadata[serviceIdentifier].name;
- configCode += self.tabs(1) + serviceIdentifier + '?: AWS.' + className + '.Types.ClientConfiguration;\n';
- versionsCode += self.tabs(1) + serviceIdentifier + '?: AWS.' + className + '.Types.apiVersion;\n';
- });
- configCode += '}\n';
- versionsCode += '}\n';
- code += configCode + versionsCode;
- this.writeTypingsFile('config_service_placeholders', path.join(this._sdkRootDir, 'lib'), code);
- };
- TSGenerator.prototype.getServiceApiVersions = function generateServiceApiVersions(serviceIdentifier) {
- var metadata = this.metadata;
- var versions = metadata[serviceIdentifier].versions || [];
- // transform results (to get rid of '*' and sort
- versions = versions.map(function(version) {
- return version.replace('*', '');
- }).sort();
- return versions;
- };
- /**
- * Generates class method types for a waiter.
- */
- TSGenerator.prototype.generateTypingsFromWaiters = function generateTypingsFromWaiters(className, waiterState, waiter, underlyingOperation, tabCount) {
- var code = '';
- tabCount = tabCount || 0;
- var operationName = waiter.operation.charAt(0).toLowerCase() + waiter.operation.substring(1);
- waiterState = waiterState.charAt(0).toLowerCase() + waiterState.substring(1);
- var docString = 'Waits for the ' + waiterState + ' state by periodically calling the underlying ' + className + '.' + operationName + 'operation every ' + waiter.delay + ' seconds (at most ' + waiter.maxAttempts + ' times).';
- if (waiter.description) {
- docString += ' ' + waiter.description;
- }
- // get input and output
- var inputShape = '{}';
- var outputShape = '{}';
- if (underlyingOperation.input) {
- inputShape = className + '.Types.' + underlyingOperation.input.shape;
- }
- if (underlyingOperation.output) {
- outputShape = className + '.Types.' + underlyingOperation.output.shape;
- }
- code += this.generateDocString(docString, tabCount);
- code += this.tabs(tabCount) + 'waitFor(state: "' + waiterState + '", params: ' + inputShape + ' & {$waiter?: WaiterConfiguration}, callback?: (err: AWSError, data: ' + outputShape + ') => void): Request<' + outputShape + ', AWSError>;\n';
- code += this.generateDocString(docString, tabCount);
- code += this.tabs(tabCount) + 'waitFor(state: "' + waiterState + '", callback?: (err: AWSError, data: ' + outputShape + ') => void): Request<' + outputShape + ', AWSError>;\n';
- return code;
- };
- /**
- * Returns whether a service has customizations to include.
- */
- TSGenerator.prototype.includeCustomService = function includeCustomService(serviceIdentifier) {
- // check services directory
- var servicesDir = path.join(this._sdkRootDir, 'lib', 'services');
- var fileNames = fs.readdirSync(servicesDir);
- fileNames = fileNames.filter(function(fileName) {
- return fileName === serviceIdentifier + '.d.ts';
- });
- return !!fileNames.length;
- };
- /**
- * Generates typings for classes that live on a service client namespace.
- */
- TSGenerator.prototype.generateCustomNamespaceTypes = function generateCustomNamespaceTypes(serviceIdentifier, className) {
- var self = this;
- var tsCustomizationsJson = require('./ts-customizations');
- var customClasses = [];
- var code = '';
- var serviceInfo = tsCustomizationsJson[serviceIdentifier] || null;
- // exit early if no customizations found
- if (!serviceInfo) {
- return null;
- }
- code += 'declare namespace ' + className + ' {\n';
- //generate import code
- var importCode = '';
- serviceInfo.forEach(function(data) {
- var aliases = [];
- var imports = data.imports || [];
- imports.forEach(function(pair) {
- aliases.push(pair.name + ' as ' + pair.alias);
- code += self.tabs(1) + 'export import ' + pair.name + ' = ' + pair.alias + ';\n';
- customClasses.push(pair.name);
- });
- if (aliases.length) {
- importCode += 'import {' + aliases.join(', ') + '} from \'../' + data.path + '\';\n';
- }
- });
- code += '}\n';
- return {
- importCode: importCode,
- namespaceCode: code,
- customClassNames: customClasses
- };
- };
- TSGenerator.prototype.containsEventStreams = function containsEventStreams(model) {
- var shapeNames = Object.keys(model.shapes);
- for (var name of shapeNames) {
- if (model.shapes[name].eventstream) {
- return true;
- }
- }
- return false;
- };
- TSGenerator.prototype.containsDocumentType = function containsDocumentType(model) {
- var shapeNames = Object.keys(model.shapes);
- for (var name of shapeNames) {
- if (model.shapes[name].isDocument) {
- return true;
- }
- }
- return false;
- };
- /**
- * Generates the typings for a service based on the serviceIdentifier.
- */
- TSGenerator.prototype.processServiceModel = function processServiceModel(serviceIdentifier) {
- var model = this.loadServiceApi(serviceIdentifier);
- pruneShapes(model);
- var self = this;
- var code = '';
- var className = this.metadata[serviceIdentifier].name;
- var customNamespaces = this.generateCustomNamespaceTypes(serviceIdentifier, className);
- var customClassNames = customNamespaces ? customNamespaces.customClassNames : [];
- var waiters = model.waiters || Object.create(null);
- var waiterKeys = Object.keys(waiters);
- // generate imports
- code += 'import {Request} from \'../lib/request\';\n';
- code += 'import {Response} from \'../lib/response\';\n';
- code += 'import {AWSError} from \'../lib/error\';\n';
- var hasCustomizations = this.includeCustomService(serviceIdentifier);
- var parentClass = hasCustomizations ? className + 'Customizations' : 'Service';
- if (hasCustomizations) {
- code += 'import {' + parentClass + '} from \'../lib/services/' + serviceIdentifier + '\';\n';
- } else {
- code += 'import {' + parentClass + '} from \'../lib/service\';\n';
- }
- if (waiterKeys.length) {
- code += 'import {WaiterConfiguration} from \'../lib/service\';\n';
- }
- code += 'import {ServiceConfigurationOptions} from \'../lib/service\';\n';
- // get any custom config options
- var customConfig = this.generateCustomConfigFromMetadata(serviceIdentifier);
- var hasCustomConfig = !!customConfig.length;
- var customConfigTypes = ['ServiceConfigurationOptions'];
- code += 'import {ConfigBase as Config} from \'../lib/config-base\';\n';
- if (hasCustomConfig) {
- // generate import statements and custom config type
- customConfig.forEach(function(config) {
- code += 'import {' + config.INTERFACE + '} from \'../lib/' + config.FILE_NAME + '\';\n';
- customConfigTypes.push(config.INTERFACE);
- });
- }
- if (this.containsEventStreams(model)) {
- code += 'import {EventStream} from \'../lib/event-stream/event-stream\';\n';
- }
- if (this.containsDocumentType(model)) {
- code += 'import {DocumentType} from \'../lib/model\';\n';
- }
- // import custom namespaces
- if (customNamespaces) {
- code += customNamespaces.importCode;
- }
- code += 'interface Blob {}\n';
- // generate methods
- var modelOperations = model.operations;
- var operationKeys = Object.keys(modelOperations);
- code += 'declare class ' + className + ' extends ' + parentClass + ' {\n';
- // create constructor
- code += this.generateDocString('Constructs a service object. This object has one method for each API operation.', 1);
- code += this.tabs(1) + 'constructor(options?: ' + className + '.Types.ClientConfiguration' + ')\n';
- code += this.tabs(1) + 'config: Config & ' + className + '.Types.ClientConfiguration' + ';\n';
- operationKeys.forEach(function (operationKey) {
- code += self.generateTypingsFromOperations(className, modelOperations[operationKey], operationKey, 1);
- });
- // generate waitFor methods
- waiterKeys.forEach(function (waitersKey) {
- var waiter = waiters[waitersKey];
- var operation = modelOperations[waiter.operation];
- code += self.generateTypingsFromWaiters(className, waitersKey, waiter, operation, 1);
- });
- code += '}\n';
- // check for static classes on namespace
- if (customNamespaces) {
- code += customNamespaces.namespaceCode;
- }
- // shapes should map to interfaces
- var modelShapes = model.shapes;
- // iterate over each shape
- var shapeKeys = Object.keys(modelShapes);
- code += 'declare namespace ' + className + ' {\n';
- // preprocess shapes to fetch out needed dependency. e.g. "streaming": true
- shapeKeys.forEach(function (shapeKey) {
- var modelShape = modelShapes[shapeKey];
- var streamTypeList = self.extractTypesDependOnStream(shapeKey, modelShape);
- for (var streamType of streamTypeList) {
- self.streamTypes[streamType] = true;
- }
- });
- shapeKeys.forEach(function (shapeKey) {
- var modelShape = modelShapes[shapeKey];
- code += self.generateTypingsFromShape(model, shapeKey, modelShape, 1, customClassNames);
- });
- //add extra dependencies like 'streaming'
- if (Object.keys(self.streamTypes).length !== 0) {
- var insertPos = code.indexOf('interface Blob {}');
- code = code.slice(0, insertPos) + 'import {Readable} from \'stream\';\n' + code.slice(insertPos);
- }
- this.streamTypes = {};
- code += this.generateDocString('A string in YYYY-MM-DD format that represents the latest possible API version that can be used in this service. Specify \'latest\' to use the latest possible version.', 1);
- code += this.tabs(1) + 'export type apiVersion = "' + this.getServiceApiVersions(serviceIdentifier).join('"|"') + '"|"latest"|string;\n';
- code += this.tabs(1) + 'export interface ClientApiVersions {\n';
- code += this.generateDocString('A string in YYYY-MM-DD format that represents the latest possible API version that can be used in this service. Specify \'latest\' to use the latest possible version.', 2);
- code += this.tabs(2) + 'apiVersion?: apiVersion;\n';
- code += this.tabs(1) + '}\n';
- code += this.tabs(1) + 'export type ClientConfiguration = ' + customConfigTypes.join(' & ') + ' & ClientApiVersions;\n';
- // export interfaces under Types namespace for backwards-compatibility
- code += this.generateDocString('Contains interfaces for use with the ' + className + ' client.', 1);
- code += this.tabs(1) + 'export import Types = ' + className + ';\n';
- code += '}\n';
- code += 'export = ' + className + ';\n';
- return code;
- };
- /**
- * Write Typings file to the specified directory.
- */
- TSGenerator.prototype.writeTypingsFile = function writeTypingsFile(name, directory, code) {
- fs.writeFileSync(path.join(directory, name + '.d.ts'), code);
- };
- /**
- * Create the typescript definition files for every service.
- */
- TSGenerator.prototype.generateAllClientTypings = function generateAllClientTypings() {
- this.fillApiModelFileNames();
- var self = this;
- var metadata = this.metadata;
- // Iterate over every service
- var serviceIdentifiers = Object.keys(metadata);
- serviceIdentifiers.forEach(function(serviceIdentifier) {
- var code = self.processServiceModel(serviceIdentifier);
- self.writeTypingsFile(serviceIdentifier, self._clientsDir, code);
- });
- };
- /**
- * Create the typescript definition files for the all and browser_default exports.
- */
- TSGenerator.prototype.generateGroupedClients = function generateGroupedClients() {
- var metadata = this.metadata;
- var allCode = '';
- var browserCode = '';
- // Iterate over every service
- var serviceIdentifiers = Object.keys(metadata);
- serviceIdentifiers.forEach(function(serviceIdentifier) {
- var className = metadata[serviceIdentifier].name;
- var code = 'export import ' + className + ' = require(\'./' + serviceIdentifier + '\');\n';
- allCode += code;
- if (metadata[serviceIdentifier].cors) {
- browserCode += code;
- }
- });
- this.writeTypingsFile('all', this._clientsDir, allCode);
- this.writeTypingsFile('browser_default', this._clientsDir, browserCode);
- };
- module.exports = TSGenerator;
|