UNPKG

@sketch-hq/sketch-assistant-types

Version:
834 lines 28.1 kB
import FileFormat from '@sketch-hq/sketch-file-format-ts'; import { JSONSchema7 } from 'json-schema'; import { CoreProperties as PackageJson } from '@schemastore/package'; /** * Re-export the specific version of the file format supported by this package. */ export { FileFormat as FileFormat }; /** * Optional value. */ export declare type Maybe<T> = T | undefined | null; /** * Utility function for gathering metadata about Sketch file images. Is isomorphic in the sense that * its signature shouldn’t change across platforms. */ export declare type GetImageMetadata = (ref: string, filepath: string) => Promise<ImageMetadata>; /** * When rules request metadata for a Sketch file image it is returned in this format. */ export declare type ImageMetadata = { width: number; height: number; ref: string; }; /** * Value or arbitrarily nested array of values. */ export declare type ValueOrArray<T> = T | Array<ValueOrArray<T>>; /** * The shape of an ES Module with a default export built with TypeScript or Babel with ES Module * interoperability. */ export declare type ESModuleInterop<T> = { __esModule: boolean; default: T; }; /** * Module export that is either a CommonJS export or an ES Module interop export. */ export declare type MaybeESModule<T> = T | ESModuleInterop<T>; /** * Unwrap an array type up one level, e.g. extract Foo from Foo[]. */ export declare type Unarray<T> = T extends Array<infer U> ? U : T; /** * Iterable object that uses a generator function. */ export declare type GeneratorIterable<T> = { [Symbol.iterator]: () => Generator<T>; }; /** * A simple primitive type alias to represent a JSON Pointer string. */ export declare type JsonPointer = string; /** * Represents a Sketch file that is on disk. Collates the filepath with an object typed as Contents * from the file format. */ export declare type SketchFile = { filepath: string; contents: FileFormat.Contents; }; /** * The root document object with `_class` `document` in a parsed Sketch file. */ export declare type DocumentObject = FileFormat.Contents['document']; /** * Union of all possible objects in a parsed Sketch file that have a `_class` property, including * the root document object. */ export declare type SketchFileObject = FileFormat.AnyObject | DocumentObject; /** * Look-up a pointer value using a Sketch file object reference. */ export declare type PointerMap = Map<SketchFileObject, JsonPointer>; /** * A record of all object ids found in the file. */ export declare type ObjectIdSet = Set<string>; /** * A cache of Sketch file objects. Each key is a `_class` value from the file * format, and the corresponding value is an array of file objects with matching * `_class` values. */ export declare type ObjectCache = { [key in keyof FileFormat.ClassMap]: FileFormat.ClassMap[key][]; } & { anyGroup: FileFormat.AnyGroup[]; anyLayer: FileFormat.AnyLayer[]; document: DocumentObject[]; }; /** * Same as ObjectCache, except the cache values are an iterable that yields * the file objects, rather than a simple array. */ export declare type IterableObjectCache = { [key in keyof ObjectCache]: GeneratorIterable<Unarray<ObjectCache[key]>>; }; /** * A processed Sketch file collates a SketchFile object along with various data structures suited * for efficiently inspecting its contents. */ export declare type ProcessedSketchFile = { /** * A cache of all local objects in the file, i.e. objects native to the file, not from a library. */ objects: ObjectCache; /** * A cache of all foreign objects in the file, i.e. objects or children of objects from libraries. */ foreignObjects: ObjectCache; /** * A map of file object references to JSON Pointer strings. */ pointers: PointerMap; /** * A set of all object ids found in the file. */ objectIds: ObjectIdSet; /** * The original SketchFile object that was processed. */ original: SketchFile; /** * Statistics about the processed file. */ profile: { /** * Number of Sketch objetcs in the file. */ numObjects: number; /** * Time taken for processing in milliseconds. */ time: number; }; }; /** * The expected shape of the Sketch file workspace used with Assistants. This is * where Sketch persists a file's Assistants configuration. First and foremost * it's a valid package.json, with the dependencies specifying the active * Assistants - every dependency is expected to be a package exporting a valid * Assistant on its default export. It additionally persists what's being * ignored during the Assistant runs. */ export declare type Workspace = PackageJson & { ignore?: IgnoreConfig; }; /** * Information about what to ignore during an Assistant run. Pages can be * ignored entirely, whereas Assistant rules can either be ignored entirely too, * or only ignored for certain file objects. */ export declare type IgnoreConfig = { pages: string[]; assistants: { [assistantName: string]: { rules: { [ruleName: string]: { allObjects: true; } | { allObjects: true; objects: []; } | { objects: []; } | {}; }; }; }; }; /** * Contains a flag indicating whether the run operation has been cancelled by * the outer environment. All long running processes happening during a run * (like cache creation, rule invocation etc.) should exit early as soon as a * cancellation is detected. */ export declare type CancelToken = { cancelled: boolean; } | { cancelled: 1 | 0; }; /** * Contains a flag indicating whether a rule has timed out. */ export declare type TimeoutToken = { timedOut: boolean; }; /** * A map of Assistant packages, keyed by Assistant package name. Since the * package map is often supplied externally, by an outer layer (e.g. by Sketch * to the Assistant runner) we type the packages as unknown. */ export declare type AssistantPackageMap = { [assistantName: string]: unknown; }; /** * Input required for running a group of multiple Assistant packages * against a single Sketch file. */ export declare type RunInput = { /** * The Assistants to run. */ assistants: AssistantPackageMap; /** * What to ignore during the run. */ ignore: IgnoreConfig; /** * Processed Sketch file to run the Assistants against. */ processedFile: ProcessedSketchFile; /** * GetImageMetadata implmentation. */ getImageMetadata: GetImageMetadata; /** * Object from the external environment carrying the cancelled flag. */ cancelToken: CancelToken; /** * Environment. */ env: AssistantEnv; timeBudgets: { /** * Time budget in milliseconds for the entire run to complete. During the run this budget is * dividedly evenly between each active rule. */ totalMs: number; /** * Minimum rule run time in milliseconds, irrespective of its share of the total budget. */ minRuleTimeoutMs: number; /** * Maximum rule run time in milliseconds, irrespective of its share of the total budget. */ maxRuleTimeoutMs: number; }; }; /** * The output from running a group of Assistants. Results are grouped by Assistant * name, and indicate either success or error. */ export declare type RunOutput = { /** * Mirror input in the output, for easier processing of results. */ input: RunInput; /** * Ignore directives are pruned during the run to remove orphaned data * (non-existant pages, assistants, rules and objects), and returned in the * output. */ ignore: IgnoreConfig; /** * Results per Assistant. * "error": The Assistant run failed entirely. * "success": One or more rules ran successfully. */ assistants: { [assistantName: string]: { code: 'error'; error: AssistantErrorResult; } | { code: 'success'; result: AssistantSuccessResult; }; }; }; /** * Profiling statistics about a run. */ export declare type RunOutputProfile = { file: { time: number; totalObjects: number; objectCounts: { [key: string]: { count: number; }; }; }; assistants: { [assistantName: string]: { time: number; violations: number; ruleErrors: number; rules: { [ruleName: string]: { violations: number; time: number; }; }; }; }; }; /** * The run has failed to the extent that collating a RunOutput object is not * possible, and the runner function promise rejects instead. */ export declare type RunRejection = { /** * Human readable message describing the rejection. */ message: string; /** * runError: Something unexpected has gone badly wrong. * cancelled: Run cancelled via cancellation signal from outside. */ code: 'runError' | 'cancelled'; }; /** * JavaScript errors encountered during rule invocation normalised into plain objects. */ export declare type RuleError = { assistantName: string; ruleName: string; message: string; stack: string; code: 'error' | 'timeout'; }; /** * The result of running a single Assistant that errored and did not complete. */ export declare type AssistantErrorResult = { message: string; }; /** * The result of successfully running a single assistant to completion. Note that * even if the Assistant encounters some rules that crash and produce `ruleErrors` then that * doesn't invalidate the whole result. */ export declare type AssistantSuccessResult = { /** * Assistant grades the document as follows: * "pass" No violations with severity level "error" present * "fail" One or more violations with severitu level "error" present * "unknown" Grade could not be determined, for example due to one or more rules timing-out */ grade: 'fail' | 'pass' | 'unknown'; /** * One or more `violations` implies the assistant’s rules found issues with the Sketch document. */ violations: Violation[]; /** * One or more `ruleErrors` implies that some rules encountered errors. */ ruleErrors: RuleError[]; /** * Metadata relating to the Assistant that produced the result. */ metadata: { assistant: { config: AssistantConfig; name: string; }; rules: { [ruleName: string]: { name: string; title: string; description: string; debug: boolean; runtime?: AssistantRuntime; }; }; }; /** * Object containing information about how long each rule took to execute. */ profile: { ruleTimings: { [ruleName: string]: number; }; }; }; /** * Contains all the values and utils exposed to individual rule functions. */ export declare type RuleContext = { utils: RuleUtils; file: ProcessedSketchFile; assistant: AssistantDefinition; getImageMetadata: GetImageMetadata; env: AssistantEnv; }; /** * Function for creating a rule utilties object scoped to a specific assistant rule. */ export declare type RuleUtilsCreator = (ruleName: string, timeoutToken: TimeoutToken) => RuleUtils; /** * Object containing utilities passed into rule functions. Where needed the util functions are * scoped to the current rule, e.g. `report` reports a violation for the current rule and * `getOption` retrieves an option value for the current rule etc. */ export declare type RuleUtils = { /** * Report one or more violations. */ report: (message: string, ...objects: SketchFileObject[]) => void; /** * Contains an iterator for each type of object in the Sketch file. */ objects: IterableObjectCache; /** * Contains an iterator for each type of object in the Sketch file, filtered so it contains _only_ * foreign objects, that is, objects that have been imported from a library. */ foreignObjects: IterableObjectCache; /** * Determine if a given Sketch file object has been ignored in the run's IgnoreConfig. Ignored * objects are automatically filtered out while iterating objects, however if you use a different * mechanism to traverse the Sketch file you should manually determine whether an object is ignored * before reporting it in a violation. */ isObjectIgnored: (object: SketchFileObject) => boolean; /** * Rules can be a good Assistant citizen by checking the return value of this function during any * long running calculations - if it returns `true` then the rule should bail out of any further * calculations and exit as soon as possible. This function will return `true` for two reasons - * the run has been cancelled entirely, or the current rule has timed-out. Note: If the rule is * mainly driven by the `utils.objects` and `utils.foreignObjects` iterators then there's no need * to call this function, since these loops will be terminated early if required automatically. */ shouldExitEarly: () => boolean; /** * Get a rule option value by name. Should throw if the rule hasn’t been configured properly in * the current assistant context, since it’s essential that every rule activated in an assistant is * fully configured. */ getOption: <T = unknown>(option: string) => T; /** * Returns metadata for a given Sketch file image. */ getImageMetadata: (ref: string) => Promise<ImageMetadata>; /** * Return the md5 hash of an object. Keys are deeply sorted for a stable hash. * Useful for comparing deep similarity of Sketch document objects. By default * the keys `do_objectID` and `$pointer` are excluded since they will always * be different. */ objectHash: (o: {}, excludeKeys?: string[]) => string; /** * Compare two document objects for deep equality. */ objectsEqual: (o1: {}, o2: {}, excludeKeys?: string[]) => boolean; /** * Resolve a JSON Pointer string to the value in the Sketch file it points to. */ evalPointer: (pointer: JsonPointer) => unknown; /** * Determine the JSON Pointer for a given object in a Sketch file. */ getObjectPointer: (object: SketchFileObject) => JsonPointer | undefined; /** * Returns the immediate parent object of a Sketch file object. */ getObjectParent: (object: SketchFileObject) => unknown; /** * Returns an array of parent objects for a given Sketch file object, all the way to the root. */ getObjectParents: (object: SketchFileObject) => unknown[]; /** * Compares two style objects for equality. */ styleEq: (s1: FileFormat.Style | undefined, s2: FileFormat.Style | undefined) => boolean; /** * Compares two text style objects for equality. */ textStyleEq: (s1: FileFormat.Style | undefined, s2: FileFormat.Style | undefined) => boolean; /** * Reduces a text style object into a string hash and returns it. */ textStyleHash: (style: Partial<FileFormat.Style> | undefined) => string; /** * Reduces a style object into a string hash and returns it. */ styleHash: (style: Partial<FileFormat.Style> | undefined) => string; }; /** * A violation collates all the information about a problem, and is the fundamental way an Assistant * communicates these to the outer environment. */ export declare type Violation = { message: string; assistantName: string; ruleName: string; severity: ViolationSeverity; objects: Array<Partial<{ id: string; pointer: string; name: string; class: string; }>>; }; /** * Define the possible violation severity levels. */ export declare enum ViolationSeverity { info = 1, warn = 2, error = 3 } /** * Type representing the package.json for an Assistant project/package. Extends the standard * package.json spec with a `sketch-assistant` object containing human readable `title` and `description` * strings, an icon path and an `i18n` object of translations for the `title` and `description`. All * properties are defined as optional since package.json files are user supplied, so their contents * cannot be strictly enforced. * * Example * * { * "name": "my-assistant", * "sketch-assistant": { * "title": "My Assistant", * "description": "An example Assistant", * "icon": "https://www.domain.com/some/hosted/image.png", * "i18n": { * "zh-Hans": { * "title": "...", * "description": "..." * } * } * }, * ... * } */ export declare type AssistantPackageJson = PackageJson & Partial<{ /** * The Sketch equivalent to the standard package.json `main` property. Used for indicating the * JavaScript entrypoint Sketch should use when running the Assistant in its JavaScriptCore * environment. Note that unlike a Node environment which supports CommonJS modules via the * `require` function, Sketch's JavaScript environment does not include any module system, so * entrypoints for Sketch referenced via this `sketch` property must be bundled into a single * file in a similar way to a web app, typically using Webpack. Also note that Sketch's * JavaScriptCore environment is based on modern WebKit (minus the browser APIs), so files * should only need to be transpiled down to ES6 at the most. */ sketch: string; /** * Object containing configuration specific to the Assistant. */ 'sketch-assistant': Partial<{ /** * Human readable Assistant title for display in Sketch. */ title: string; /** * Human readable Assistant description for display in Sketch. */ description: string; /** * Assistant icon/image for display in Sketch. Should be a fully qualified uri to a publicly * hosted image file. */ icon: string; /** * Optional object to contain internationalised versions of the above strings. If this object * is present, and contains strings for Sketch's currently active locale, then those will be * used in preference. */ i18n: Partial<{ [locale: string]: Partial<{ title: string; description: string; icon: string; }>; }>; }>; }>; /** * Assistants can run within Node, or the JavaScriptCore runtime provided by Sketch. This type * enumerates the two possibilities. */ export declare enum AssistantRuntime { Sketch = "Sketch", Node = "Node" } /** * Ambient environmental information for assistants, typically provided by an outer assistant runner. */ export declare type AssistantEnv = { /** * Language tag indicating the current user’s locale. Use this to optionally internationalize your * assistant’s content. Its exact value is not guaranteed, so an appropriate fallback locale should * always be used for unrecognized values. For assistants running in Sketch it’s value is likely * to be either `en` or `zh-Hans`. */ locale: string | undefined; /** * Indicates whether the assistant is running in Node or Sketch. */ runtime: AssistantRuntime; }; /** * Canonical definition of an assistant, that is, an async function that given an AssistantEnv * will resolve with a concrete AssistantDefinition. Assistants therefore are able to defer final * creation until invoked by a runner, and which point critical contextual information such as the * locale are available. */ export declare type Assistant = (env: AssistantEnv) => Promise<AssistantDefinition>; /** * Defines the expected type for the default export from an assistant package entrypoint. It allows * an assistant to be expressed as either a single assistant or an array of assistants that should be extended and merged before a run operation. */ export declare type AssistantPackage = ValueOrArray<Assistant>; /** * Concrete assistant definition that can be invoked against a Sketch file during a lint run. * Fundamentally assistants collate a list of rules with configuration for those rules, alongside * metadata about the assistant. */ export declare type AssistantDefinition = { /** * List of rules owned by the assistant. */ rules: RuleDefinition[]; /** * Assistant configuration activates and configures one or more rules present in its rule list. */ config: AssistantConfig; /** * Assistant name is the same as its package name, i.e. the `name` property in its `package.json`. */ name: string; }; /** * Canonical rule definition combining the rule function, its option schema creator with other * basic metadata. */ export declare type RuleDefinition = { rule: RuleFunction; /** * The rule name acts as its unique id and should combine an identifier for the rule with the parent * assistant’s name separated by a slash, e.g. "assistant-name/rule-name" */ name: string; /** * Human readable title for the rule. Can either be a string e.g. "Groups should not be empty", or * a function that returns a string, which enables the title to interpolate configuration values * e.g. "Maximum height is 44px". */ title: string | ((ruleConfig: RuleConfig) => string); /** * Longer human readable description for the rule. */ description: string | ((ruleConfig: RuleConfig) => string); /** * Rules that require options (i.e. are not just simply "on" or "off") need to describe the schema * for those options by implementing this function */ getOptions?: RuleOptionsCreator; /** * Flags a rule as for internal/development purposes only */ debug?: boolean; /** * Indicates rule compatibility. For cross-platform rules this property can be omitted. */ runtime?: AssistantRuntime; }; /** * A map of rule configs, keyed by the rule’s name. */ export declare type RuleConfigGroup = { [ruleName: string]: Maybe<RuleConfig>; }; /** * Contains the assistant configuration. */ export declare type AssistantConfig = { /** * Default severity to be used for violations raised by rules that haven’t been configured with * their own explicit severity level. */ defaultSeverity?: Maybe<ViolationSeverity>; /** * Configuration to be applied to the rules available to the assistant. */ rules: RuleConfigGroup; }; /** * Creates the configuration JSON Schema for the given assistant definition. */ export declare type AssistantConfigSchemaCreator = (assistant: AssistantDefinition) => JSONSchema7; /** * User-defined rule options with these names are forbidden. */ export declare enum ReservedRuleOptionNames { active = "active", severity = "severity", ruleTitle = "ruleTitle" } /** * Contains the configuration for an individual rule. */ export declare type RuleConfig = { /** * Whether the rule is active or not. Alternatively omitting the rule from the assistant config is * the same as setting this flag to `false`. */ [ReservedRuleOptionNames.active]: boolean; /** * Optional custom severity for violations reported by the rule. If omitted the default severity is * used instead. */ [ReservedRuleOptionNames.severity]?: ViolationSeverity; /** * Optional custom rule title to replace the title defined by the RuleDefinition. Can be used to * supply descriptive rule titles that can only be defined alongside configuration - for example * to title a rule "Page names should start with emojis" alongside regex patterns that enforces * the same. */ [ReservedRuleOptionNames.ruleTitle]?: string; /** * User-defined rule option are mixed into this object. */ [key: string]: Maybe<RuleOption>; }; /** * The valid set of types available for individual rule options. */ export declare type RuleOption = string | number | boolean | string[] | { [key: string]: string | number | boolean | string[]; }[]; /** * Async function that is expected to perform the core rule logic using the values and helper * functions provided by the passed in RuleInvocationContext object. */ export declare type RuleFunction = (context: RuleContext) => Promise<void>; /** * JSONSchema `properties` value. */ export declare type JSONSchemaProps = { [key: string]: JSONSchema7; }; /** * Creates rule option schema properties for a number option. */ export declare type NumberOptionCreator = (ops: { name: string; title: string; description: string; defaultValue?: number; minimum?: number; maximum?: number; }) => JSONSchemaProps; /** * Creates rule option schema properties for an integer option. */ export declare type IntegerOptionCreator = (ops: { name: string; title: string; description: string; defaultValue?: number; minimum?: number; maximum?: number; }) => JSONSchemaProps; /** * Creates rule option schema properties for a string option. */ export declare type StringOptionCreator = (ops: { name: string; title: string; description: string; defaultValue?: string; minLength?: number; maxLength?: number; pattern?: string; }) => JSONSchemaProps; /** * Creates rule option schema properties for a boolean option. */ export declare type BoolOptionCreator = (ops: { name: string; title: string; description: string; defaultValue?: boolean; }) => JSONSchemaProps; /** * Creates rule option schema properties for a string enum option. */ export declare type StringEnumOptionCreator = (ops: { name: string; title: string; description: string; defaultValue?: string; values: string[]; valueTitles: string[]; }) => JSONSchemaProps; /** * Creates rule option schema properties for a string array option. */ export declare type StringArrayOptionCreator = (ops: { name: string; title: string; description: string; defaultValue?: string[]; minLength?: number; maxLength?: number; pattern?: string; }) => JSONSchemaProps; /** * Creates rule option schema properties for an object array option. */ export declare type ObjectArrayOptionCreator = (ops: { name: string; title: string; description: string; props: JSONSchemaProps[]; minLength?: number; maxLength?: number; }) => JSONSchemaProps; /** * A function that should be implemented on rule definitions if they need to define custom options. */ export declare type RuleOptionsCreator = (helpers: RuleOptionHelpers) => JSONSchemaProps[]; /** * An object of helper functions for creating the different types of option schemas. */ export declare type RuleOptionHelpers = { numberOption: NumberOptionCreator; integerOption: IntegerOptionCreator; stringOption: StringOptionCreator; booleanOption: BoolOptionCreator; stringArrayOption: StringArrayOptionCreator; stringEnumOption: StringEnumOptionCreator; objectArrayOption: ObjectArrayOptionCreator; }; /** * Combines a set of JSON Schema `properties` objects into a single valid JSON Schema. */ export declare type RuleOptionSchemaCreator = (ops: JSONSchemaProps[]) => JSONSchema7; //# sourceMappingURL=types.d.ts.map