@zeplin/cli
Advanced tools
Comparing version 0.1.6 to 0.2.0
{ | ||
"projects": [ | ||
"5c05af12810c5b2c7e470e64" | ||
], | ||
"projects": ["aasd"], | ||
"styleguides": [], | ||
"baseURLs": [ | ||
"links": [ | ||
{ | ||
@@ -22,6 +20,11 @@ "name": "My Lovely SB", | ||
"name": "Zeplin", | ||
"type": "custom", | ||
"type": "designsystem", | ||
"url": "https://designsystem.zeplin.io/" | ||
} | ||
], | ||
"github": { | ||
"branch": "master", | ||
"repository": "zeplin/connected-components", | ||
"url": "https://github.com" | ||
}, | ||
"components": [ | ||
@@ -37,10 +40,16 @@ { | ||
"path": "MyComponent.jsx", | ||
"urlPaths": { | ||
"storybook": "?path=/story/button", | ||
"custom": "components/button.jsx" | ||
}, | ||
"zeplinNames": [ | ||
"button selected", | ||
"button secondary" | ||
] | ||
], | ||
"storybook": { | ||
"kind": "HeleKind", | ||
"stories": ["HeleS tory1", "HeleSt ory2"] | ||
}, | ||
"styleguidist": { | ||
"kind": "HeleStyleguidist" | ||
}, | ||
"designsystem": { | ||
"urlPath": "/example/Button" | ||
} | ||
}, | ||
@@ -50,8 +59,2 @@ { | ||
"path": "MyComponent.jsx", | ||
"urlPaths": { | ||
"storybook": "?path=/story/textarea", | ||
"styleguidist": "#textarea", | ||
"github": "components/textarea.jsx", | ||
"custom": "components/textarea.jsx" | ||
}, | ||
"zeplinNames": [ | ||
@@ -58,0 +61,0 @@ "asdasd" |
{ | ||
"name": "@zeplin/cli", | ||
"version": "0.1.6", | ||
"version": "0.2.0", | ||
"description": "Zeplin CLI", | ||
@@ -33,3 +33,3 @@ "main": "./dist/src/app", | ||
"@types/fs-extra": "^8.0.0", | ||
"@types/hapi__joi": "^15.0.4", | ||
"@types/hapi__joi": "^16.0.3", | ||
"@types/inquirer": "^6.5.0", | ||
@@ -52,3 +52,3 @@ "@types/jest": "^24.0.18", | ||
"dependencies": { | ||
"@hapi/joi": "^16.1.4", | ||
"@hapi/joi": "^16.1.7", | ||
"axios": "^0.19.0", | ||
@@ -55,0 +55,0 @@ "commander": "^3.0.1", |
@@ -1,2 +0,2 @@ | ||
import { AxiosInstance, AxiosRequestConfig } from "axios"; | ||
import { AxiosInstance } from "axios"; | ||
import { LoginRequest, LoginResponse } from "./interfaces"; | ||
@@ -7,3 +7,2 @@ import { ConnectedComponentList } from "../commands/connect/interfaces"; | ||
axios: AxiosInstance; | ||
constructor(config?: AxiosRequestConfig); | ||
login(request: LoginRequest): Promise<LoginResponse>; | ||
@@ -10,0 +9,0 @@ generateToken(zeplinToken: string): Promise<string>; |
@@ -23,7 +23,4 @@ "use strict"; | ||
class ZeplinApi { | ||
constructor(config) { | ||
constructor() { | ||
this.axios = axios_1.default.create({ baseURL: defaults_1.defaults.api.baseURL }); | ||
if (config) { | ||
Object.assign(this.axios.defaults, config); | ||
} | ||
} | ||
@@ -30,0 +27,0 @@ login(request) { |
@@ -20,10 +20,16 @@ #!/usr/bin/env node | ||
const connect_1 = require("./commands/connect"); | ||
const login_1 = require("./commands/login"); | ||
const command_1 = require("./util/command"); | ||
const program = new commander_1.default.Command(); | ||
function collectionValue(value, previous) { | ||
// Replace default value | ||
if (previous.length === 1 && previous[0] === defaults_1.defaults.commands.connect.filePath[0]) { | ||
return [value]; | ||
function createCollector() { | ||
let cleared = false; | ||
function collectionValue(value, previous) { | ||
// Clear default values on first call | ||
if (!cleared) { | ||
cleared = true; | ||
return [value]; | ||
} | ||
return previous.concat([value]); | ||
} | ||
return previous.concat([value]); | ||
return collectionValue; | ||
} | ||
@@ -36,10 +42,10 @@ program | ||
connectCommand.description("Connect components to code") | ||
.option("-f, --file <file>", "Full path to components file", collectionValue, defaults_1.defaults.commands.connect.filePath) | ||
.option("-d, --dev-mode", "Activate development mode", defaults_1.defaults.commands.connect.devMode) | ||
.option("-f, --file <file>", "Full path to components file", createCollector(), defaults_1.defaults.commands.connect.filePaths) | ||
.option("-d, --dev", "Activate development mode", defaults_1.defaults.commands.connect.devMode) | ||
.option("--port <port>", "Optional port number for development mode", defaults_1.defaults.commands.connect.port) | ||
.option("-p, --plugin <plugin>", "NPM package name of a Zeplin CLI connect plugin", collectionValue, []) | ||
.option("-p, --plugin <plugin>", "NPM package name of a Zeplin CLI connect plugin", createCollector(), []) | ||
.action(command_1.commandRunner((options) => __awaiter(void 0, void 0, void 0, function* () { | ||
const connectOptions = { | ||
configFiles: options.file, | ||
devMode: options.devMode, | ||
devMode: options.dev, | ||
plugins: options.plugin, | ||
@@ -50,2 +56,4 @@ devModePort: options.port | ||
}))); | ||
program.command("login") | ||
.action(command_1.commandRunner(login_1.login)); | ||
program.on("command:*", () => { | ||
@@ -52,0 +60,0 @@ program.outputHelp(); |
@@ -34,17 +34,49 @@ "use strict"; | ||
name: joi_1.default.string().optional(), | ||
urlPaths: joi_1.default.object().pattern(joi_1.default.string(), joi_1.default.string()).optional() | ||
storybook: joi_1.default.object({ | ||
kind: joi_1.default.string(), | ||
stories: joi_1.default.array().items(joi_1.default.string()).optional() | ||
}).optional(), | ||
styleguidist: joi_1.default.object({ | ||
kind: joi_1.default.string() | ||
}).optional() | ||
}); | ||
const githubConfigSchema = joi_1.default.object({ | ||
repository: joi_1.default.string(), | ||
branch: joi_1.default.string().optional(), | ||
url: joi_1.default.string().optional() | ||
}); | ||
const componentConfigFileSchema = joi_1.default.object({ | ||
projects: joi_1.default.array().items(joi_1.default.string()).optional(), | ||
styleguides: joi_1.default.array().items(joi_1.default.string()).optional(), | ||
baseURLs: joi_1.default.array().items(urlConfigSchema).optional(), | ||
components: joi_1.default.array().items(componentConfigSchema).min(1) | ||
}).or("projects", "styleguides"); | ||
links: joi_1.default.array().items(urlConfigSchema).optional(), | ||
components: joi_1.default.array().items(componentConfigSchema).min(1), | ||
github: githubConfigSchema.optional() | ||
}).custom((value, helpers) => { | ||
if (value.projects && value.styleguides) { | ||
if (value.projects.length === 0 && value.styleguides.length === 0) { | ||
throw new Error("at least one of `projects` or `styleguides` properties must contain 1 item."); | ||
} | ||
} | ||
else if (value.projects) { | ||
if (value.projects.length === 0) { | ||
throw new Error("`projects` must contain at least 1 item."); | ||
} | ||
} | ||
else if (value.styleguides) { | ||
if (value.styleguides.length === 0) { | ||
throw new Error("`styleguides` must contain at least 1 item."); | ||
} | ||
} | ||
else { | ||
return helpers.error("object.missing", { peersWithLabels: ["projects", "styleguides"] }); | ||
} | ||
return value; | ||
}); | ||
const getComponentConfigFile = (filePath) => __awaiter(void 0, void 0, void 0, function* () { | ||
const file = yield fileUtil.readJsonFile(filePath); | ||
const { error, value } = componentConfigFileSchema.validate(file, { stripUnknown: true, presence: "required" }); | ||
const { error } = componentConfigFileSchema.validate(file, { stripUnknown: true, presence: "required" }); | ||
if (error) { | ||
throw new errors_1.CLIError(`Oops! Looks like ${filePath} has some problems: ${error.message}`); | ||
} | ||
return value; | ||
return file; | ||
}); | ||
@@ -51,0 +83,0 @@ exports.getComponentConfigFile = getComponentConfigFile; |
@@ -23,3 +23,3 @@ "use strict"; | ||
if (devMode) { | ||
console.log("Starting development server..."); | ||
console.log("Starting development server…"); | ||
const devServer = new server_1.ConnectDevServer(connectedBarrels); | ||
@@ -30,6 +30,5 @@ yield devServer.start(devModePort); | ||
else { | ||
console.log("Uploading all connected components into Zeplin..."); | ||
console.log("Uploading all connected components into Zeplin…"); | ||
const service = new service_1.ConnectedComponentsService(); | ||
yield service.uploadConnectedBarrels(connectedBarrels); | ||
// Await updateConnectedBarrels(connectedBarrels); | ||
console.log("Awesome! All components are successfully connected on Zeplin."); | ||
@@ -36,0 +35,0 @@ } |
import { ComponentConfig, ConnectPlugin } from "connect-plugin"; | ||
export interface Url { | ||
name: string; | ||
name?: string; | ||
type: string; | ||
url: string; | ||
} | ||
export interface GithubConfig { | ||
repository: string; | ||
branch?: string; | ||
url?: string; | ||
} | ||
export interface ComponentConfigFile { | ||
projects?: string[]; | ||
styleguides?: string[]; | ||
baseURLs: Url[]; | ||
links: Url[]; | ||
components: ComponentConfig[]; | ||
github?: GithubConfig; | ||
} | ||
@@ -13,0 +19,0 @@ export interface Data { |
@@ -24,2 +24,3 @@ "use strict"; | ||
const url_join_1 = __importDefault(require("url-join")); | ||
const defaults_1 = require("../../config/defaults"); | ||
// Helper method to initialize plugin classses | ||
@@ -36,2 +37,10 @@ const constructConnectPlugin = (Constructor) => new Constructor(); | ||
}; | ||
const prepareStorybookLinks = (baseUrl, storybookConfig) => { | ||
const { kind, stories } = storybookConfig; | ||
const urlEncodedKind = encodeURIComponent(kind); | ||
if (stories) { | ||
return stories.map(story => url_join_1.default(baseUrl, `?selectedKind=${urlEncodedKind}&selectedStory=${encodeURIComponent(story)}`)); | ||
} | ||
return [url_join_1.default(baseUrl, `?selectedKind=${kind}`)]; | ||
}; | ||
const importPlugins = (plugins) => __awaiter(void 0, void 0, void 0, function* () { | ||
@@ -53,3 +62,3 @@ try { | ||
exports.importPlugins = importPlugins; | ||
const connectComponentConfig = (component, baseURLs, plugins) => __awaiter(void 0, void 0, void 0, function* () { | ||
const connectComponentConfig = (component, componentConfigFile, plugins) => __awaiter(void 0, void 0, void 0, function* () { | ||
const data = []; | ||
@@ -66,13 +75,34 @@ if (plugins.length > 0) { | ||
} | ||
// TODO move urlPath preparation to service layer | ||
const urlPaths = []; | ||
if (component.urlPaths) { | ||
const configUrlPaths = component.urlPaths; | ||
Object.keys(configUrlPaths).forEach(type => { | ||
const baseUrl = baseURLs.find(u => u.type === type); | ||
const url = configUrlPaths[type]; | ||
if (baseUrl) { | ||
urlPaths.push({ name: baseUrl.name, type, url: url_join_1.default(baseUrl.url, url) }); | ||
if (componentConfigFile.links) { | ||
componentConfigFile.links.forEach(link => { | ||
const { name, type, url } = link; | ||
const foundType = Object.keys(component).some(key => key === link.type); | ||
if (foundType) { | ||
const config = component[type]; | ||
if (type === "storybook") { | ||
const preparedUrls = prepareStorybookLinks(url, config); | ||
preparedUrls.forEach(preparedUrl => { | ||
urlPaths.push({ name, type, url: preparedUrl }); | ||
}); | ||
} | ||
else if (type === "styleguidist") { | ||
urlPaths.push({ name, type, url: url_join_1.default(url, `#${encodeURIComponent(config.kind)}`) }); | ||
} | ||
else { | ||
urlPaths.push({ name, type, url: url_join_1.default(url, config.urlPath) }); | ||
} | ||
} | ||
}); | ||
} | ||
if (componentConfigFile.github) { | ||
const branch = componentConfigFile.github.branch || defaults_1.defaults.github.branch; | ||
const url = componentConfigFile.github.url || defaults_1.defaults.github.url; | ||
const { repository } = componentConfigFile.github; | ||
urlPaths.push({ | ||
type: "github", | ||
url: `${url}/${repository}/blob/${branch}/${component.path}` | ||
}); | ||
} | ||
return { | ||
@@ -87,3 +117,3 @@ path: component.path, | ||
const connectComponentConfigFile = (componentConfigFile, connectPlugins) => __awaiter(void 0, void 0, void 0, function* () { | ||
const connectedComponents = yield Promise.all(componentConfigFile.components.map(component => connectComponentConfig(component, componentConfigFile.baseURLs, connectPlugins))); | ||
const connectedComponents = yield Promise.all(componentConfigFile.components.map(component => connectComponentConfig(component, componentConfigFile, connectPlugins))); | ||
return { | ||
@@ -90,0 +120,0 @@ projects: componentConfigFile.projects || [], |
@@ -34,7 +34,6 @@ "use strict"; | ||
yield this.upload(authToken, connectedBarrelComponents); | ||
return; | ||
} | ||
} | ||
else { | ||
throw error; | ||
} | ||
throw error; | ||
} | ||
@@ -41,0 +40,0 @@ }); |
export declare const defaults: { | ||
commands: { | ||
connect: { | ||
filePath: string[]; | ||
filePaths: string[]; | ||
devMode: boolean; | ||
@@ -13,2 +13,6 @@ port: number; | ||
}; | ||
github: { | ||
url: string; | ||
branch: string; | ||
}; | ||
}; |
@@ -6,3 +6,3 @@ "use strict"; | ||
connect: { | ||
filePath: [".zeplin/components.json"], | ||
filePaths: [".zeplin/components.json"], | ||
devMode: false, | ||
@@ -14,5 +14,9 @@ port: 9756 | ||
baseURL: process.env.API_BASE_URL || "https://api.zeplin.io", | ||
clientId: "5d78a9f01b4e9c0a1e9b505b" | ||
clientId: process.env.API_CLIENT_ID || "5dd27af376f8bf5094f6ebe6" | ||
}, | ||
github: { | ||
url: "https://github.com", | ||
branch: "master" | ||
} | ||
}; | ||
//# sourceMappingURL=defaults.js.map |
@@ -63,3 +63,4 @@ "use strict"; | ||
console.log("Looks like no authentication token has been found in the environment."); | ||
yield this.promptForLogin(); | ||
this.authToken = yield this.promptForLogin(); | ||
authFileUtil.saveAuthToken(this.authToken, { ignoreErrors: true }); | ||
} | ||
@@ -80,3 +81,3 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
console.log("Login into Zeplin..."); | ||
console.log("Login into Zeplin…"); | ||
const credentials = yield inquirer_1.default.prompt([ | ||
@@ -98,5 +99,3 @@ { | ||
const authToken = yield this.zeplinApi.generateToken(loginResponse.token); | ||
authFileUtil.saveAuthToken(authToken); | ||
this.authToken = authToken; | ||
return validate(this.authToken); | ||
return validate(authToken); | ||
}); | ||
@@ -103,0 +102,0 @@ } |
@@ -10,2 +10,9 @@ import { PrismLang } from "./prism"; | ||
} | ||
export interface StorybookConfig { | ||
kind: string; | ||
stories?: string[]; | ||
} | ||
export interface StyleguidistConfig { | ||
kind: string; | ||
} | ||
export interface ComponentConfig { | ||
@@ -15,3 +22,5 @@ path: string; | ||
name?: string; | ||
urlPaths?: UrlPath; | ||
storybook?: StorybookConfig; | ||
styleguidist?: StyleguidistConfig; | ||
[key: string]: any; | ||
} | ||
@@ -18,0 +27,0 @@ export interface ConnectPlugin { |
@@ -1,2 +0,5 @@ | ||
export declare function saveAuthToken(authToken: string): Promise<void>; | ||
export declare function getTokenFileName(): string; | ||
export declare function saveAuthToken(authToken: string, options?: { | ||
ignoreErrors: boolean; | ||
}): Promise<void>; | ||
export declare function readAuthToken(): Promise<string | undefined>; |
@@ -19,3 +19,7 @@ "use strict"; | ||
const TOKEN_FILE_NAME = ".zeplinrc"; | ||
function saveAuthToken(authToken) { | ||
function getTokenFileName() { | ||
return path_1.default.join(os_1.default.homedir(), TOKEN_FILE_NAME); | ||
} | ||
exports.getTokenFileName = getTokenFileName; | ||
function saveAuthToken(authToken, options = { ignoreErrors: false }) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
@@ -27,3 +31,5 @@ const tokenFilename = path_1.default.join(os_1.default.homedir(), TOKEN_FILE_NAME); | ||
catch (error) { | ||
// Ignore | ||
if (!options.ignoreErrors) { | ||
throw error; | ||
} | ||
// TODO add logging utility for verbose logs | ||
@@ -30,0 +36,0 @@ } |
{ | ||
"name": "@zeplin/cli", | ||
"version": "0.1.6", | ||
"version": "0.2.0", | ||
"description": "Zeplin CLI", | ||
@@ -33,3 +33,3 @@ "main": "./dist/src/app", | ||
"@types/fs-extra": "^8.0.0", | ||
"@types/hapi__joi": "^15.0.4", | ||
"@types/hapi__joi": "^16.0.3", | ||
"@types/inquirer": "^6.5.0", | ||
@@ -52,3 +52,3 @@ "@types/jest": "^24.0.18", | ||
"dependencies": { | ||
"@hapi/joi": "^16.1.4", | ||
"@hapi/joi": "^16.1.7", | ||
"axios": "^0.19.0", | ||
@@ -55,0 +55,0 @@ "commander": "^3.0.1", |
@@ -28,3 +28,3 @@ # Zeplin CLI | ||
| -f, --file <file> | Full path to components config file | .zeplin/components.json | | ||
| -d, --dev-mode | Activate development mode | false | | ||
| -d, --dev | Activate development mode | false | | ||
| --port <port> | Optional port number for development mode | 9756 | | ||
@@ -31,0 +31,0 @@ | -p, --plugin <plugin> | NPM package name of a Zeplin CLI connect plugin | | |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
117556
114
1782
Updated@hapi/joi@^16.1.7