зеркало из https://github.com/microsoft/TACO.git
Trying out alternate approach to taco-utils
We can split up the TacoUtility module across multiple files, but we need to manually ensure that the mapping between what the generated code does and what the type system says is correct. The approach that I'm trying here should work fine UNLESS we need types from other node modules to be part of the type system; e.g. if we had a function that took an express.Request or returned a Q.Promise then it will need a different approach.
This commit is contained in:
Родитель
a1850f8d00
Коммит
613fb40217
|
@ -0,0 +1,90 @@
|
|||
|
||||
import resourcesManager = require("./resources-manager");
|
||||
import ResourcesManager = resourcesManager.ResourcesManager;
|
||||
|
||||
import utilHelper = require("./util-helper");
|
||||
import UtilHelper = utilHelper.UtilHelper;
|
||||
|
||||
module TacoUtility {
|
||||
export class BuildInfo {
|
||||
public status: string;
|
||||
/**
|
||||
* BuildInfo holds relevant information about a particular build, including its identifier, what kind of build was requested, and the status of the build
|
||||
* This information is passed around both within the remote build server, and back to the client
|
||||
*/
|
||||
public changeList: {
|
||||
deletedFiles: string[];
|
||||
changedFiles: string[];
|
||||
addedPlugins: string[];
|
||||
deletedPlugins: string[];
|
||||
deletedFilesIos: string[];
|
||||
changedFilesIos: string[];
|
||||
addedPluginsIos: string[];
|
||||
deletedPluginsIos: string[];
|
||||
};
|
||||
public statusTime: Date;
|
||||
public cordovaVersion: string;
|
||||
public buildCommand: string;
|
||||
public configuration: string;
|
||||
public options: any;
|
||||
public buildDir: string;
|
||||
public buildLang: string;
|
||||
public buildPlatform: string;
|
||||
public submissionTime: Date;
|
||||
public buildNumber: number;
|
||||
|
||||
public messageId: string;
|
||||
public messageArgs: any[];
|
||||
public message: string;
|
||||
|
||||
public tgzFilePath: string;
|
||||
public appDir: string;
|
||||
public appName: string;
|
||||
|
||||
public webDebugProxyPort: number;
|
||||
|
||||
constructor(params: { buildNumber?: number; status?: string; cordovaVersion?: string; buildCommand?: string; configuration?: string; options?: any; buildDir?: string; buildLang?: string; buildPlatform?: string }) {
|
||||
this.buildNumber = params.buildNumber;
|
||||
this.status = params.status;
|
||||
this.cordovaVersion = params.cordovaVersion;
|
||||
this.buildCommand = params.buildCommand;
|
||||
this.configuration = params.configuration;
|
||||
this.options = params.options;
|
||||
this.buildDir = params.buildDir;
|
||||
this.buildLang = params.buildLang;
|
||||
this.buildPlatform = params.buildPlatform;
|
||||
this.submissionTime = new Date();
|
||||
this.changeList = null;
|
||||
}
|
||||
|
||||
public static createNewBuildInfoFromDataObject(buildInfoData: any): BuildInfo {
|
||||
var bi: any = new BuildInfo(buildInfoData);
|
||||
Object.keys(buildInfoData).forEach(function (k: string): void {
|
||||
bi[k] = buildInfoData[k];
|
||||
});
|
||||
return bi;
|
||||
}
|
||||
|
||||
public updateStatus(status: string, messageId?: string, ...messageArgs: any[]): void {
|
||||
this.status = status;
|
||||
this.messageId = messageId;
|
||||
if (arguments.length > 2) {
|
||||
this.messageArgs = UtilHelper.getOptionalArgsArrayFromFunctionCall(arguments, 2);
|
||||
}
|
||||
|
||||
this.statusTime = new Date();
|
||||
}
|
||||
|
||||
public localize(req: any): BuildInfo {
|
||||
if (this.messageId) {
|
||||
this.message = ResourcesManager.getStringForLanguage(req, this.messageId, this.messageArgs);
|
||||
} else {
|
||||
this.message = ResourcesManager.getStringForLanguage(req, "Build-" + this.status);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export = TacoUtility;
|
|
@ -0,0 +1,48 @@
|
|||
/// <reference path="../typings/node.d.ts" />
|
||||
/// <reference path="../typings/elementtree.d.ts" />
|
||||
/// <reference path="../typings/unorm.d.ts" />
|
||||
|
||||
import et = require("elementtree");
|
||||
import fs = require("fs");
|
||||
import path = require("path");
|
||||
var unorm = require("unorm"); // Note no import: the compiler will remove the require since we don't use the unorm object, we just need it to add String.normalize
|
||||
|
||||
import tacoUtility = require("./util-helper");
|
||||
import UtilHelper = tacoUtility.UtilHelper
|
||||
|
||||
module TacoUtility {
|
||||
export class CordovaConfig {
|
||||
/** CordovaConfig is a class for parsing the config.xml file for Cordova projects */
|
||||
private _doc: et.ElementTree;
|
||||
|
||||
constructor(configXmlPath: string) {
|
||||
var contents = UtilHelper.readFileContentsSync(configXmlPath, "utf-8");
|
||||
this._doc = new et.ElementTree(et.XML(contents));
|
||||
}
|
||||
|
||||
public id(): string {
|
||||
return this._doc.getroot().attrib["id"];
|
||||
}
|
||||
|
||||
public name(): string {
|
||||
var el = this._doc.find("name");
|
||||
return el && el.text && el.text.trim().normalize();
|
||||
}
|
||||
|
||||
public version(): string {
|
||||
var el = this._doc.getroot();
|
||||
return el && el.attrib && el.attrib["version"];
|
||||
}
|
||||
|
||||
public preferences(): { [key: string]: string } {
|
||||
var data: { [key: string]: string } = {};
|
||||
var preferences = this._doc.findall("preference");
|
||||
preferences.forEach(function (preference: et.XMLElement): void {
|
||||
data[preference.attrib["name"]] = preference.attrib["value"];
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
export = TacoUtility;
|
|
@ -0,0 +1,146 @@
|
|||
/// <reference path="../typings/node.d.ts" />
|
||||
import fs = require("fs");
|
||||
import path = require("path");
|
||||
|
||||
module TacoUtility {
|
||||
export class ResourcesManager {
|
||||
private static Resources: { [key: string]: any; } = null;
|
||||
private static SupportedLanguages: string[] = null;
|
||||
private static DefaultLanguage: string = "en";
|
||||
|
||||
public static init(language: string, resourcesDir: string): void {
|
||||
ResourcesManager.Resources = {};
|
||||
ResourcesManager.SupportedLanguages = [];
|
||||
fs.readdirSync(resourcesDir).forEach(function (filename: string): void {
|
||||
try {
|
||||
ResourcesManager.Resources[filename.toLowerCase()] = ResourcesManager.loadLanguage(filename, resourcesDir);
|
||||
ResourcesManager.SupportedLanguages.push(filename.toLowerCase());
|
||||
} catch (e) {
|
||||
// Folder was not a valid resource; ignore it
|
||||
}
|
||||
});
|
||||
|
||||
ResourcesManager.DefaultLanguage = ResourcesManager.bestLanguageMatchOrDefault(language);
|
||||
}
|
||||
|
||||
// For unit tests
|
||||
public static teardown(): void {
|
||||
ResourcesManager.Resources = null;
|
||||
ResourcesManager.SupportedLanguages = null;
|
||||
}
|
||||
|
||||
/** ...optionalArgs is only there for typings, function rest params */
|
||||
public static getString(id: string, ...optionalArgs: any[]): string {
|
||||
var args = ResourcesManager.getOptionalArgsArrayFromFunctionCall(arguments, 1);
|
||||
return ResourcesManager.getStringForLanguage(ResourcesManager.DefaultLanguage, id, args);
|
||||
}
|
||||
|
||||
/** ** ...optionalArgs is only there for typings, function rest params** */
|
||||
public static getStringForLanguage(requestOrAcceptLangs: any, id: string, ...optionalArgs: any[]): string {
|
||||
if (!ResourcesManager.Resources) {
|
||||
throw new Error("Resources have not been loaded");
|
||||
}
|
||||
|
||||
var lang = ResourcesManager.bestLanguageMatchOrDefault(requestOrAcceptLangs);
|
||||
|
||||
var s = ResourcesManager.Resources[lang][id];
|
||||
if (!s) {
|
||||
return s;
|
||||
} else if (Array.isArray(s)) {
|
||||
// Allow longer resources strings to be specified as a list of strings, which represent multiple lines
|
||||
s = s.join("\n");
|
||||
}
|
||||
|
||||
/*All args passed to current function:
|
||||
you can call getString('foo', 'bar', 'baz') or getString('foo',['bar', 'baz'])
|
||||
and the utility function will extract ['bar', 'baz'] as args in both cases*/
|
||||
var args = ResourcesManager.getOptionalArgsArrayFromFunctionCall(arguments, 2);
|
||||
if (args) {
|
||||
for (var i: number = 0; i < args.length; i++) {
|
||||
s = s.replace("{" + i + "}", args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static bestLanguageMatchOrDefault(requestOrAcceptLangs: any): string {
|
||||
var lang = ResourcesManager.bestLanguageMatch(requestOrAcceptLangs);
|
||||
if (!ResourcesManager.Resources[lang]) {
|
||||
lang = ResourcesManager.DefaultLanguage;
|
||||
}
|
||||
|
||||
return lang.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* requestOrAcceptLangs can either be:
|
||||
* A string, with format "LangSpec[,LangSpec]*" where LangSpec is "Language[;anything]"
|
||||
* e.g. "pl,fr-FR;q=0.3,en-US;q=0.1" is interpreted as "pl" or "fr-FR" or "en-US". Currently we ignore provided quality (q) values
|
||||
* An array, which we assume is an array of strings representing languages such as "pl" or "fr-FR"
|
||||
* A (express-style) HTTP Request object, with a headers property specifing "accept-language" in a string, as above
|
||||
*
|
||||
* This allows us to handle simple cases of a single string, as well as more complex cases where a client specifies
|
||||
* multiple preferences.
|
||||
*/
|
||||
private static bestLanguageMatch(requestOrAcceptLangs: any): string {
|
||||
if (Array.isArray(requestOrAcceptLangs)) {
|
||||
return ResourcesManager.getBestLanguageFromArray(requestOrAcceptLangs);
|
||||
}
|
||||
|
||||
var langString: string;
|
||||
if (!requestOrAcceptLangs) {
|
||||
return ResourcesManager.DefaultLanguage;
|
||||
} else if (typeof requestOrAcceptLangs === "string") {
|
||||
langString = requestOrAcceptLangs;
|
||||
} else if (requestOrAcceptLangs.headers) {
|
||||
langString = requestOrAcceptLangs.headers["accept-language"] || "";
|
||||
} else {
|
||||
throw new Error("Unsupported type of argument for acceptLangs: " + (typeof requestOrAcceptLangs));
|
||||
}
|
||||
|
||||
return ResourcesManager.getBestLanguageFromArray(langString.split(",").map(function (l: string): string { return l.split(";")[0]; }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of languages, we try to find an exact match if we can, and we fall back to a primary language otherwise.
|
||||
* e.g. "fr-CA" will use "fr-CA" resources if present, but will fall back to "fr" resources if they are available
|
||||
*/
|
||||
private static getBestLanguageFromArray(acceptLangs: string[]): string {
|
||||
var primaryLanguageMatch: string = null;
|
||||
for (var i: number = 0; i < acceptLangs.length; ++i) {
|
||||
var lang: string = acceptLangs[i].toLowerCase();
|
||||
var primaryLang = lang.split("-")[0];
|
||||
if (ResourcesManager.SupportedLanguages.indexOf(lang) !== -1) {
|
||||
// Exact match on full language header, which could include the region
|
||||
return lang;
|
||||
}
|
||||
|
||||
if (ResourcesManager.SupportedLanguages.indexOf(primaryLang) !== -1) {
|
||||
// Match on primary language (e.g. it from it-CH). We may find a better match later, so continue looking.
|
||||
primaryLanguageMatch = primaryLang;
|
||||
}
|
||||
}
|
||||
|
||||
return primaryLanguageMatch;
|
||||
}
|
||||
|
||||
private static loadLanguage(language: string, resourcesDir: string): any {
|
||||
var resourcesPath = path.join(resourcesDir, language, "resources.json");
|
||||
return require(resourcesPath);
|
||||
}
|
||||
|
||||
private static getOptionalArgsArrayFromFunctionCall(functionArguments: IArguments, startFrom: number): any[] {
|
||||
if (functionArguments.length <= startFrom) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Array.isArray(functionArguments[startFrom])) {
|
||||
return functionArguments[startFrom];
|
||||
}
|
||||
|
||||
return Array.prototype.slice.apply(functionArguments, [startFrom]);
|
||||
}
|
||||
}
|
||||
}
|
||||
export = TacoUtility;
|
|
@ -8,301 +8,17 @@ import fs = require ("fs");
|
|||
import path = require ("path");
|
||||
var unorm = require("unorm"); // Note no import: the compiler will remove the require since we don't use the unorm object, we just need it to add String.normalize
|
||||
|
||||
import buildInfo = require("./build-info");
|
||||
import cordovaConfig = require("./cordova-config");
|
||||
import resourcesManager = require("./resources-manager");
|
||||
import utilHelper = require("./util-helper");
|
||||
|
||||
module TacoUtility {
|
||||
// put more classes here, known limitation that classes in external modules CANNOT span multiple files
|
||||
export class ResourcesManager {
|
||||
private static Resources: { [key: string]: any; } = null;
|
||||
private static SupportedLanguages: string[] = null;
|
||||
private static DefaultLanguage: string = "en";
|
||||
|
||||
public static init(language: string, resourcesDir: string): void {
|
||||
ResourcesManager.Resources = {};
|
||||
ResourcesManager.SupportedLanguages = [];
|
||||
fs.readdirSync(resourcesDir).forEach(function (filename: string): void {
|
||||
try {
|
||||
ResourcesManager.Resources[filename.toLowerCase()] = ResourcesManager.loadLanguage(filename, resourcesDir);
|
||||
ResourcesManager.SupportedLanguages.push(filename.toLowerCase());
|
||||
} catch (e) {
|
||||
// Folder was not a valid resource; ignore it
|
||||
}
|
||||
});
|
||||
|
||||
ResourcesManager.DefaultLanguage = ResourcesManager.bestLanguageMatchOrDefault(language);
|
||||
}
|
||||
|
||||
// For unit tests
|
||||
public static teardown(): void {
|
||||
ResourcesManager.Resources = null;
|
||||
ResourcesManager.SupportedLanguages = null;
|
||||
}
|
||||
|
||||
/** ...optionalArgs is only there for typings, function rest params */
|
||||
public static getString(id: string, ...optionalArgs: any[]): string {
|
||||
var args = ResourcesManager.getOptionalArgsArrayFromFunctionCall(arguments, 1);
|
||||
return ResourcesManager.getStringForLanguage(ResourcesManager.DefaultLanguage, id, args);
|
||||
}
|
||||
|
||||
/** ** ...optionalArgs is only there for typings, function rest params** */
|
||||
public static getStringForLanguage(requestOrAcceptLangs: any, id: string, ...optionalArgs: any[]): string {
|
||||
if (!ResourcesManager.Resources) {
|
||||
throw new Error("Resources have not been loaded");
|
||||
}
|
||||
|
||||
var lang = ResourcesManager.bestLanguageMatchOrDefault(requestOrAcceptLangs);
|
||||
|
||||
var s = ResourcesManager.Resources[lang][id];
|
||||
if (!s) {
|
||||
return s;
|
||||
} else if (Array.isArray(s)) {
|
||||
// Allow longer resources strings to be specified as a list of strings, which represent multiple lines
|
||||
s = s.join("\n");
|
||||
}
|
||||
|
||||
/*All args passed to current function:
|
||||
you can call getString('foo', 'bar', 'baz') or getString('foo',['bar', 'baz'])
|
||||
and the utility function will extract ['bar', 'baz'] as args in both cases*/
|
||||
var args = ResourcesManager.getOptionalArgsArrayFromFunctionCall(arguments, 2);
|
||||
if (args) {
|
||||
for (var i: number = 0; i < args.length; i++) {
|
||||
s = s.replace("{" + i + "}", args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static bestLanguageMatchOrDefault(requestOrAcceptLangs: any): string {
|
||||
var lang = ResourcesManager.bestLanguageMatch(requestOrAcceptLangs);
|
||||
if (!ResourcesManager.Resources[lang]) {
|
||||
lang = ResourcesManager.DefaultLanguage;
|
||||
}
|
||||
|
||||
return lang.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* requestOrAcceptLangs can either be:
|
||||
* A string, with format "LangSpec[,LangSpec]*" where LangSpec is "Language[;anything]"
|
||||
* e.g. "pl,fr-FR;q=0.3,en-US;q=0.1" is interpreted as "pl" or "fr-FR" or "en-US". Currently we ignore provided quality (q) values
|
||||
* An array, which we assume is an array of strings representing languages such as "pl" or "fr-FR"
|
||||
* A (express-style) HTTP Request object, with a headers property specifing "accept-language" in a string, as above
|
||||
*
|
||||
* This allows us to handle simple cases of a single string, as well as more complex cases where a client specifies
|
||||
* multiple preferences.
|
||||
*/
|
||||
private static bestLanguageMatch(requestOrAcceptLangs: any): string {
|
||||
if (Array.isArray(requestOrAcceptLangs)) {
|
||||
return ResourcesManager.getBestLanguageFromArray(requestOrAcceptLangs);
|
||||
}
|
||||
|
||||
var langString: string;
|
||||
if (!requestOrAcceptLangs) {
|
||||
return ResourcesManager.DefaultLanguage;
|
||||
} else if (typeof requestOrAcceptLangs === "string") {
|
||||
langString = requestOrAcceptLangs;
|
||||
} else if (requestOrAcceptLangs.headers) {
|
||||
langString = requestOrAcceptLangs.headers["accept-language"] || "";
|
||||
} else {
|
||||
throw new Error("Unsupported type of argument for acceptLangs: " + (typeof requestOrAcceptLangs));
|
||||
}
|
||||
|
||||
return ResourcesManager.getBestLanguageFromArray(langString.split(",").map(function (l: string): string { return l.split(";")[0]; }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of languages, we try to find an exact match if we can, and we fall back to a primary language otherwise.
|
||||
* e.g. "fr-CA" will use "fr-CA" resources if present, but will fall back to "fr" resources if they are available
|
||||
*/
|
||||
private static getBestLanguageFromArray(acceptLangs: string[]): string {
|
||||
var primaryLanguageMatch: string = null;
|
||||
for (var i: number = 0; i < acceptLangs.length; ++i) {
|
||||
var lang: string = acceptLangs[i].toLowerCase();
|
||||
var primaryLang = lang.split("-")[0];
|
||||
if (ResourcesManager.SupportedLanguages.indexOf(lang) !== -1) {
|
||||
// Exact match on full language header, which could include the region
|
||||
return lang;
|
||||
}
|
||||
|
||||
if (ResourcesManager.SupportedLanguages.indexOf(primaryLang) !== -1) {
|
||||
// Match on primary language (e.g. it from it-CH). We may find a better match later, so continue looking.
|
||||
primaryLanguageMatch = primaryLang;
|
||||
}
|
||||
}
|
||||
|
||||
return primaryLanguageMatch;
|
||||
}
|
||||
|
||||
private static loadLanguage(language: string, resourcesDir: string): any {
|
||||
var resourcesPath = path.join(resourcesDir, language, "resources.json");
|
||||
return require(resourcesPath);
|
||||
}
|
||||
|
||||
private static getOptionalArgsArrayFromFunctionCall(functionArguments: IArguments, startFrom: number): any[] {
|
||||
if (functionArguments.length <= startFrom) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Array.isArray(functionArguments[startFrom])) {
|
||||
return functionArguments[startFrom];
|
||||
}
|
||||
|
||||
return Array.prototype.slice.apply(functionArguments, [startFrom]);
|
||||
}
|
||||
}
|
||||
|
||||
export class CordovaConfig {
|
||||
/** CordovaConfig is a class for parsing the config.xml file for Cordova projects */
|
||||
private _doc: et.ElementTree;
|
||||
|
||||
constructor(configXmlPath: string) {
|
||||
var contents = UtilHelper.readFileContentsSync(configXmlPath, "utf-8");
|
||||
this._doc = new et.ElementTree(et.XML(contents));
|
||||
}
|
||||
|
||||
public id(): string {
|
||||
return this._doc.getroot().attrib["id"];
|
||||
}
|
||||
|
||||
public name(): string {
|
||||
var el = this._doc.find("name");
|
||||
return el && el.text && el.text.trim().normalize();
|
||||
}
|
||||
|
||||
public version(): string {
|
||||
var el = this._doc.getroot();
|
||||
return el && el.attrib && el.attrib["version"];
|
||||
}
|
||||
|
||||
public preferences(): { [key: string]: string } {
|
||||
var data: { [key: string]: string } = {};
|
||||
var preferences = this._doc.findall("preference");
|
||||
preferences.forEach(function (preference: et.XMLElement): void {
|
||||
data[preference.attrib["name"]] = preference.attrib["value"];
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export class UtilHelper {
|
||||
private static InvalidAppNameChars = {
|
||||
34: "\"",
|
||||
36: "$",
|
||||
38: "&",
|
||||
39: "/",
|
||||
60: "<",
|
||||
92: "\\"
|
||||
};
|
||||
/** Converts an untyped argument into a boolean in a "sensible" way, treating only the string "true" as true rather than any non-empty string * */
|
||||
public static argToBool(input: any): boolean {
|
||||
if (typeof input === "string") {
|
||||
return input.toLowerCase() === "true";
|
||||
}
|
||||
|
||||
return !!input;
|
||||
}
|
||||
|
||||
public static readFileContentsSync(filename: string, encoding?: string): string {
|
||||
var contents = fs.readFileSync(filename, (encoding || "utf-8"));
|
||||
if (contents) {
|
||||
contents = contents.replace(/^\uFEFF/, ""); // Windows is the BOM
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
public static getOptionalArgsArrayFromFunctionCall(functionArguments: IArguments, startFrom: number): any[] {
|
||||
if (functionArguments.length <= startFrom) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Array.isArray(functionArguments[startFrom])) {
|
||||
return functionArguments[startFrom];
|
||||
}
|
||||
|
||||
return Array.prototype.slice.apply(functionArguments, [startFrom]);
|
||||
}
|
||||
}
|
||||
|
||||
export class BuildInfo {
|
||||
public status: string;
|
||||
/**
|
||||
* BuildInfo holds relevant information about a particular build, including its identifier, what kind of build was requested, and the status of the build
|
||||
* This information is passed around both within the remote build server, and back to the client
|
||||
*/
|
||||
public changeList: {
|
||||
deletedFiles: string[];
|
||||
changedFiles: string[];
|
||||
addedPlugins: string[];
|
||||
deletedPlugins: string[];
|
||||
deletedFilesIos: string[];
|
||||
changedFilesIos: string[];
|
||||
addedPluginsIos: string[];
|
||||
deletedPluginsIos: string[];
|
||||
};
|
||||
public statusTime: Date;
|
||||
public cordovaVersion: string;
|
||||
public buildCommand: string;
|
||||
public configuration: string;
|
||||
public options: any;
|
||||
public buildDir: string;
|
||||
public buildLang: string;
|
||||
public buildPlatform: string;
|
||||
public submissionTime: Date;
|
||||
public buildNumber: number;
|
||||
|
||||
public messageId: string;
|
||||
public messageArgs: any[];
|
||||
public message: string;
|
||||
|
||||
public tgzFilePath: string;
|
||||
public appDir: string;
|
||||
public appName: string;
|
||||
|
||||
public webDebugProxyPort: number;
|
||||
|
||||
constructor(params: { buildNumber?: number; status?: string; cordovaVersion?: string; buildCommand?: string; configuration?: string; options?: any; buildDir?: string; buildLang?: string; buildPlatform?: string }) {
|
||||
this.buildNumber = params.buildNumber;
|
||||
this.status = params.status;
|
||||
this.cordovaVersion = params.cordovaVersion;
|
||||
this.buildCommand = params.buildCommand;
|
||||
this.configuration = params.configuration;
|
||||
this.options = params.options;
|
||||
this.buildDir = params.buildDir;
|
||||
this.buildLang = params.buildLang;
|
||||
this.buildPlatform = params.buildPlatform;
|
||||
this.submissionTime = new Date();
|
||||
this.changeList = null;
|
||||
}
|
||||
|
||||
public static createNewBuildInfoFromDataObject(buildInfoData: any): BuildInfo {
|
||||
var bi: any = new BuildInfo(buildInfoData);
|
||||
Object.keys(buildInfoData).forEach(function (k: string): void {
|
||||
bi[k] = buildInfoData[k];
|
||||
});
|
||||
return bi;
|
||||
}
|
||||
|
||||
public updateStatus(status: string, messageId?: string, ...messageArgs: any[]): void {
|
||||
this.status = status;
|
||||
this.messageId = messageId;
|
||||
if (arguments.length > 2) {
|
||||
this.messageArgs = UtilHelper.getOptionalArgsArrayFromFunctionCall(arguments, 2);
|
||||
}
|
||||
|
||||
this.statusTime = new Date();
|
||||
}
|
||||
|
||||
public localize(req: any): BuildInfo {
|
||||
if (this.messageId) {
|
||||
this.message = ResourcesManager.getStringForLanguage(req, this.messageId, this.messageArgs);
|
||||
} else {
|
||||
this.message = ResourcesManager.getStringForLanguage(req, "Build-" + this.status);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
export var BuildInfo = buildInfo.BuildInfo;
|
||||
export var CordovaConfig = cordovaConfig.CordovaConfig;
|
||||
export var ResourcesManager = resourcesManager.ResourcesManager;
|
||||
export var UtilHelper = utilHelper.UtilHelper;
|
||||
}
|
||||
|
||||
export = TacoUtility;
|
|
@ -0,0 +1,45 @@
|
|||
/// <reference path="../typings/node.d.ts" />
|
||||
import fs = require("fs");
|
||||
|
||||
module TacoUtility {
|
||||
export class UtilHelper {
|
||||
private static InvalidAppNameChars = {
|
||||
34: "\"",
|
||||
36: "$",
|
||||
38: "&",
|
||||
39: "/",
|
||||
60: "<",
|
||||
92: "\\"
|
||||
};
|
||||
/** Converts an untyped argument into a boolean in a "sensible" way, treating only the string "true" as true rather than any non-empty string * */
|
||||
public static argToBool(input: any): boolean {
|
||||
if (typeof input === "string") {
|
||||
return input.toLowerCase() === "true";
|
||||
}
|
||||
|
||||
return !!input;
|
||||
}
|
||||
|
||||
public static readFileContentsSync(filename: string, encoding?: string): string {
|
||||
var contents = fs.readFileSync(filename,(encoding || "utf-8"));
|
||||
if (contents) {
|
||||
contents = contents.replace(/^\uFEFF/, ""); // Windows is the BOM
|
||||
}
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
public static getOptionalArgsArrayFromFunctionCall(functionArguments: IArguments, startFrom: number): any[] {
|
||||
if (functionArguments.length <= startFrom) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Array.isArray(functionArguments[startFrom])) {
|
||||
return functionArguments[startFrom];
|
||||
}
|
||||
|
||||
return Array.prototype.slice.apply(functionArguments, [startFrom]);
|
||||
}
|
||||
}
|
||||
}
|
||||
export = TacoUtility;
|
|
@ -0,0 +1,50 @@
|
|||
declare module TacoUtility {
|
||||
class BuildInfo {
|
||||
status: string;
|
||||
/**
|
||||
* BuildInfo holds relevant information about a particular build, including its identifier, what kind of build was requested, and the status of the build
|
||||
* This information is passed around both within the remote build server, and back to the client
|
||||
*/
|
||||
changeList: {
|
||||
deletedFiles: string[];
|
||||
changedFiles: string[];
|
||||
addedPlugins: string[];
|
||||
deletedPlugins: string[];
|
||||
deletedFilesIos: string[];
|
||||
changedFilesIos: string[];
|
||||
addedPluginsIos: string[];
|
||||
deletedPluginsIos: string[];
|
||||
};
|
||||
statusTime: Date;
|
||||
cordovaVersion: string;
|
||||
buildCommand: string;
|
||||
configuration: string;
|
||||
options: any;
|
||||
buildDir: string;
|
||||
buildLang: string;
|
||||
buildPlatform: string;
|
||||
submissionTime: Date;
|
||||
buildNumber: number;
|
||||
messageId: string;
|
||||
messageArgs: any[];
|
||||
message: string;
|
||||
tgzFilePath: string;
|
||||
appDir: string;
|
||||
appName: string;
|
||||
webDebugProxyPort: number;
|
||||
constructor(params: {
|
||||
buildNumber?: number;
|
||||
status?: string;
|
||||
cordovaVersion?: string;
|
||||
buildCommand?: string;
|
||||
configuration?: string;
|
||||
options?: any;
|
||||
buildDir?: string;
|
||||
buildLang?: string;
|
||||
buildPlatform?: string;
|
||||
});
|
||||
static createNewBuildInfoFromDataObject(buildInfoData: any): BuildInfo;
|
||||
updateStatus(status: string, messageId?: string, ...messageArgs: any[]): void;
|
||||
localize(req: any): BuildInfo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/// <reference path="../typings/node.d.ts" />
|
||||
/// <reference path="../typings/elementtree.d.ts" />
|
||||
/// <reference path="../typings/unorm.d.ts" />
|
||||
declare module TacoUtility {
|
||||
class CordovaConfig {
|
||||
/** CordovaConfig is a class for parsing the config.xml file for Cordova projects */
|
||||
private _doc;
|
||||
constructor(configXmlPath: string);
|
||||
id(): string;
|
||||
name(): string;
|
||||
version(): string;
|
||||
preferences(): {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/// <reference path="../typings/node.d.ts" />
|
||||
declare module TacoUtility {
|
||||
class ResourcesManager {
|
||||
private static Resources;
|
||||
private static SupportedLanguages;
|
||||
private static DefaultLanguage;
|
||||
static init(language: string, resourcesDir: string): void;
|
||||
static teardown(): void;
|
||||
/** ...optionalArgs is only there for typings, function rest params */
|
||||
static getString(id: string, ...optionalArgs: any[]): string;
|
||||
/** ** ...optionalArgs is only there for typings, function rest params** */
|
||||
static getStringForLanguage(requestOrAcceptLangs: any, id: string, ...optionalArgs: any[]): string;
|
||||
private static bestLanguageMatchOrDefault(requestOrAcceptLangs);
|
||||
/**
|
||||
* requestOrAcceptLangs can either be:
|
||||
* A string, with format "LangSpec[,LangSpec]*" where LangSpec is "Language[;anything]"
|
||||
* e.g. "pl,fr-FR;q=0.3,en-US;q=0.1" is interpreted as "pl" or "fr-FR" or "en-US". Currently we ignore provided quality (q) values
|
||||
* An array, which we assume is an array of strings representing languages such as "pl" or "fr-FR"
|
||||
* A (express-style) HTTP Request object, with a headers property specifing "accept-language" in a string, as above
|
||||
*
|
||||
* This allows us to handle simple cases of a single string, as well as more complex cases where a client specifies
|
||||
* multiple preferences.
|
||||
*/
|
||||
private static bestLanguageMatch(requestOrAcceptLangs);
|
||||
/**
|
||||
* Given a list of languages, we try to find an exact match if we can, and we fall back to a primary language otherwise.
|
||||
* e.g. "fr-CA" will use "fr-CA" resources if present, but will fall back to "fr" resources if they are available
|
||||
*/
|
||||
private static getBestLanguageFromArray(acceptLangs);
|
||||
private static loadLanguage(language, resourcesDir);
|
||||
private static getOptionalArgsArrayFromFunctionCall(functionArguments, startFrom);
|
||||
}
|
||||
}
|
|
@ -1,105 +1,11 @@
|
|||
/// <reference path="../typings/node.d.ts" />
|
||||
/// <reference path="../typings/elementtree.d.ts" />
|
||||
/// <reference path="../typings/unorm.d.ts" />
|
||||
declare module "taco-utils" {
|
||||
module TacoUtility {
|
||||
class ResourcesManager {
|
||||
private static Resources;
|
||||
private static SupportedLanguages;
|
||||
private static DefaultLanguage;
|
||||
static init(language: string, resourcesDir: string): void;
|
||||
static teardown(): void;
|
||||
/** ...optionalArgs is only there for typings, function rest params */
|
||||
static getString(id: string, ...optionalArgs: any[]): string;
|
||||
/** ** ...optionalArgs is only there for typings, function rest params** */
|
||||
static getStringForLanguage(requestOrAcceptLangs: any, id: string, ...optionalArgs: any[]): string;
|
||||
private static bestLanguageMatchOrDefault(requestOrAcceptLangs);
|
||||
/**
|
||||
* requestOrAcceptLangs can either be:
|
||||
* A string, with format "LangSpec[,LangSpec]*" where LangSpec is "Language[;anything]"
|
||||
* e.g. "pl,fr-FR;q=0.3,en-US;q=0.1" is interpreted as "pl" or "fr-FR" or "en-US". Currently we ignore provided quality (q) values
|
||||
* An array, which we assume is an array of strings representing languages such as "pl" or "fr-FR"
|
||||
* A (express-style) HTTP Request object, with a headers property specifing "accept-language" in a string, as above
|
||||
*
|
||||
* This allows us to handle simple cases of a single string, as well as more complex cases where a client specifies
|
||||
* multiple preferences.
|
||||
*/
|
||||
private static bestLanguageMatch(requestOrAcceptLangs);
|
||||
/**
|
||||
* Given a list of languages, we try to find an exact match if we can, and we fall back to a primary language otherwise.
|
||||
* e.g. "fr-CA" will use "fr-CA" resources if present, but will fall back to "fr" resources if they are available
|
||||
*/
|
||||
private static getBestLanguageFromArray(acceptLangs);
|
||||
private static loadLanguage(language, resourcesDir);
|
||||
private static getOptionalArgsArrayFromFunctionCall(functionArguments, startFrom);
|
||||
}
|
||||
class CordovaConfig {
|
||||
/** CordovaConfig is a class for parsing the config.xml file for Cordova projects */
|
||||
private _doc;
|
||||
constructor(configXmlPath: string);
|
||||
id(): string;
|
||||
name(): string;
|
||||
version(): string;
|
||||
preferences(): {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
class UtilHelper {
|
||||
private static InvalidAppNameChars;
|
||||
/** Converts an untyped argument into a boolean in a "sensible" way, treating only the string "true" as true rather than any non-empty string * */
|
||||
static argToBool(input: any): boolean;
|
||||
static readFileContentsSync(filename: string, encoding?: string): string;
|
||||
static getOptionalArgsArrayFromFunctionCall(functionArguments: IArguments, startFrom: number): any[];
|
||||
}
|
||||
class BuildInfo {
|
||||
status: string;
|
||||
/**
|
||||
* BuildInfo holds relevant information about a particular build, including its identifier, what kind of build was requested, and the status of the build
|
||||
* This information is passed around both within the remote build server, and back to the client
|
||||
*/
|
||||
changeList: {
|
||||
deletedFiles: string[];
|
||||
changedFiles: string[];
|
||||
addedPlugins: string[];
|
||||
deletedPlugins: string[];
|
||||
deletedFilesIos: string[];
|
||||
changedFilesIos: string[];
|
||||
addedPluginsIos: string[];
|
||||
deletedPluginsIos: string[];
|
||||
};
|
||||
statusTime: Date;
|
||||
cordovaVersion: string;
|
||||
buildCommand: string;
|
||||
configuration: string;
|
||||
options: any;
|
||||
buildDir: string;
|
||||
buildLang: string;
|
||||
buildPlatform: string;
|
||||
submissionTime: Date;
|
||||
buildNumber: number;
|
||||
messageId: string;
|
||||
messageArgs: any[];
|
||||
message: string;
|
||||
tgzFilePath: string;
|
||||
appDir: string;
|
||||
appName: string;
|
||||
webDebugProxyPort: number;
|
||||
constructor(params: {
|
||||
buildNumber?: number;
|
||||
status?: string;
|
||||
cordovaVersion?: string;
|
||||
buildCommand?: string;
|
||||
configuration?: string;
|
||||
options?: any;
|
||||
buildDir?: string;
|
||||
buildLang?: string;
|
||||
buildPlatform?: string;
|
||||
});
|
||||
static createNewBuildInfoFromDataObject(buildInfoData: any): BuildInfo;
|
||||
updateStatus(status: string, messageId?: string, ...messageArgs: any[]): void;
|
||||
localize(req: any): BuildInfo;
|
||||
}
|
||||
}
|
||||
export = TacoUtility;
|
||||
/// <reference path="../typings/resources-manager.d.ts" />
|
||||
/// <reference path="../typings/build-info.d.ts" />
|
||||
/// <reference path="../typings/cordova-config.d.ts" />
|
||||
/// <reference path="../typings/util-helper.d.ts" />
|
||||
|
||||
declare module "taco-utils" {
|
||||
export = TacoUtility;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
/// <reference path="../typings/node.d.ts" />
|
||||
declare module TacoUtility {
|
||||
class UtilHelper {
|
||||
private static InvalidAppNameChars;
|
||||
/** Converts an untyped argument into a boolean in a "sensible" way, treating only the string "true" as true rather than any non-empty string * */
|
||||
static argToBool(input: any): boolean;
|
||||
static readFileContentsSync(filename: string, encoding?: string): string;
|
||||
static getOptionalArgsArrayFromFunctionCall(functionArguments: IArguments, startFrom: number): any[];
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче