@shopify/theme-check-docs-updater
Advanced tools
Comparing version 2.0.3 to 2.0.4
# @shopify/theme-check-docs-updater | ||
## 2.0.4 | ||
### Patch Changes | ||
- 84f9eda: Include docset fallbacks in the theme-check-docs-updater package | ||
For when a user’s Internet connection is down or https://raw.githubusercontent.com is not accessible. | ||
- @shopify/theme-check-common@2.0.4 | ||
## 2.0.3 | ||
@@ -4,0 +14,0 @@ |
export { ThemeLiquidDocsManager } from './themeLiquidDocsManager'; | ||
export { compileJsonSchemaToFile } from './jsonSchemaCompiler'; | ||
export { Resource, Resources, downloadFile, downloadThemeLiquidDocs, } from './themeLiquidDocsDownloader'; | ||
export { root } from './utils'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.downloadThemeLiquidDocs = exports.downloadFile = exports.Resources = exports.compileJsonSchemaToFile = exports.ThemeLiquidDocsManager = void 0; | ||
exports.root = exports.downloadThemeLiquidDocs = exports.downloadFile = exports.Resources = exports.compileJsonSchemaToFile = exports.ThemeLiquidDocsManager = void 0; | ||
var themeLiquidDocsManager_1 = require("./themeLiquidDocsManager"); | ||
@@ -12,2 +12,4 @@ Object.defineProperty(exports, "ThemeLiquidDocsManager", { enumerable: true, get: function () { return themeLiquidDocsManager_1.ThemeLiquidDocsManager; } }); | ||
Object.defineProperty(exports, "downloadThemeLiquidDocs", { enumerable: true, get: function () { return themeLiquidDocsDownloader_1.downloadThemeLiquidDocs; } }); | ||
var utils_1 = require("./utils"); | ||
Object.defineProperty(exports, "root", { enumerable: true, get: function () { return utils_1.root; } }); | ||
//# sourceMappingURL=index.js.map |
@@ -7,2 +7,3 @@ "use strict"; | ||
exports.ThemeLiquidDocsManager = void 0; | ||
const node_path_1 = __importDefault(require("node:path")); | ||
const promises_1 = __importDefault(require("node:fs/promises")); | ||
@@ -12,2 +13,19 @@ const jsonSchemaCompiler_1 = require("./jsonSchemaCompiler"); | ||
const utils_1 = require("./utils"); | ||
function dataRoot() { | ||
if (process.env.WEBPACK_MODE) { | ||
return node_path_1.default.resolve(__dirname, './data'); | ||
} | ||
else { | ||
return node_path_1.default.resolve(__dirname, '../data'); | ||
} | ||
} | ||
async function fallback(name, defaultValue) { | ||
try { | ||
const content = await promises_1.default.readFile(node_path_1.default.resolve(dataRoot(), name), 'utf8'); | ||
return JSON.parse(content); | ||
} | ||
catch (_) { | ||
return defaultValue; | ||
} | ||
} | ||
class ThemeLiquidDocsManager { | ||
@@ -19,15 +37,15 @@ constructor(log = utils_1.noop) { | ||
this.filters = (0, utils_1.memo)(async () => { | ||
return this.loadResource('filters', []); | ||
return this.loadResource('filters', await fallback('filters.json', [])); | ||
}); | ||
this.objects = (0, utils_1.memo)(async () => { | ||
return this.loadResource('objects', []); | ||
return this.loadResource('objects', await fallback('objects.json', [])); | ||
}); | ||
this.tags = (0, utils_1.memo)(async () => { | ||
return this.loadResource('tags', []); | ||
return this.loadResource('tags', await fallback('tags.json', [])); | ||
}); | ||
this.systemTranslations = (0, utils_1.memo)(async () => { | ||
return this.loadResource('shopify_system_translations', {}); | ||
return this.loadResource('shopify_system_translations', await fallback('shopify_system_translations.json', {})); | ||
}); | ||
this.validateSectionSchema = (0, utils_1.memo)(async () => { | ||
const sectionSchema = await this.loadResource('section_schema', {}); | ||
const sectionSchema = await this.loadResource('section_schema', await fallback('section_schema.json', {})); | ||
return (0, jsonSchemaCompiler_1.compileJsonSchema)(sectionSchema); | ||
@@ -43,10 +61,17 @@ }); | ||
this.setup = (0, utils_1.memo)(async () => { | ||
if (!(await (0, themeLiquidDocsDownloader_1.exists)(utils_1.root))) { | ||
await promises_1.default.mkdir(utils_1.root, { recursive: true }); | ||
try { | ||
if (!(await (0, themeLiquidDocsDownloader_1.exists)(utils_1.root))) { | ||
await promises_1.default.mkdir(utils_1.root, { recursive: true }); | ||
} | ||
const local = await this.latestRevision(); | ||
await (0, utils_1.download)('latest'); | ||
const remote = await this.latestRevision(); | ||
if (local !== remote) { | ||
await Promise.all(themeLiquidDocsDownloader_1.Resources.map((resource) => (0, utils_1.download)(resource))); | ||
} | ||
} | ||
const local = await this.latestRevision(); | ||
await (0, utils_1.download)('latest'); | ||
const remote = await this.latestRevision(); | ||
if (local !== remote) { | ||
await Promise.all(themeLiquidDocsDownloader_1.Resources.map((resource) => (0, utils_1.download)(resource))); | ||
catch (error) { | ||
if (error instanceof Error) | ||
this.log(error.message); | ||
return; | ||
} | ||
@@ -53,0 +78,0 @@ }); |
import { Resource } from './themeLiquidDocsDownloader'; | ||
export declare const noop: () => void; | ||
export declare const root: string; | ||
export declare function download(file: Resource | 'latest'): Promise<void>; | ||
export declare function filePath(file: Resource | 'latest'): string; | ||
export declare function download(file: Resource | 'latest', destination?: string): Promise<void>; | ||
export declare function filePath(file: Resource | 'latest', destination?: string): string; | ||
/** Returns a cached version of a function. Only caches one result. */ | ||
@@ -7,0 +7,0 @@ export declare function memo<F extends (...args: any[]) => any>(fn: F): (...args: ArgumentTypes<F>) => ReturnType<F>; |
@@ -14,8 +14,8 @@ "use strict"; | ||
exports.root = paths.cache; | ||
function download(file) { | ||
return (0, themeLiquidDocsDownloader_1.downloadFile)(file, exports.root); | ||
function download(file, destination = exports.root) { | ||
return (0, themeLiquidDocsDownloader_1.downloadFile)(file, destination); | ||
} | ||
exports.download = download; | ||
function filePath(file) { | ||
return node_path_1.default.join(exports.root, `${file}.json`); | ||
function filePath(file, destination = exports.root) { | ||
return node_path_1.default.join(destination, `${file}.json`); | ||
} | ||
@@ -22,0 +22,0 @@ exports.filePath = filePath; |
{ | ||
"name": "@shopify/theme-check-docs-updater", | ||
"version": "2.0.3", | ||
"version": "2.0.4", | ||
"description": "Scripts to initialize theme-check data with assets from the theme-liquid-docs repo.", | ||
@@ -28,2 +28,3 @@ "main": "dist/index.js", | ||
"build:ts": "tsc -b tsconfig.build.json", | ||
"postbuild": "node scripts/cli.js download data", | ||
"test": "vitest", | ||
@@ -33,3 +34,3 @@ "type-check": "tsc --noEmit" | ||
"dependencies": { | ||
"@shopify/theme-check-common": "^2.0.3", | ||
"@shopify/theme-check-common": "^2.0.4", | ||
"ajv": "^8.12.0", | ||
@@ -36,0 +37,0 @@ "env-paths": "^2.2.1", |
#!/usr/bin/env node | ||
const path = require('path'); | ||
const { downloadThemeLiquidDocs, compileJsonSchemaToFile } = require(path.resolve( | ||
const fs = require('fs'); | ||
const { downloadThemeLiquidDocs, compileJsonSchemaToFile, root } = require(path.resolve( | ||
__dirname, | ||
@@ -17,5 +18,7 @@ '../dist', | ||
Acceptable values: | ||
download <DIR> \t\tDownloads all appropriate documentation and JSON Schemas from theme-liquid-docs. | ||
compile-json-schemas <DIR> \tCompiles JSON schemas in the specified directory. | ||
Usage: | ||
download <dir> \t\tDownloads all docsets and JSON Schemas to the specified directory. | ||
compile-json-schemas <dir> \tCompiles JSON schemas in the specified directory. | ||
root \tPrints the default docsets root directory. | ||
clear-cache \tClears the default docsets root directory. | ||
`); | ||
@@ -47,2 +50,12 @@ process.exit(1); | ||
break; | ||
case 'root': | ||
console.log(root); | ||
break; | ||
case 'clear-cache': | ||
console.log(`Removing '${root}'`); | ||
fs.rmSync(root, { recursive: true }); | ||
break; | ||
default: | ||
@@ -49,0 +62,0 @@ console.log(`Unknown command: ${args[0]}`); |
@@ -9,1 +9,2 @@ export { ThemeLiquidDocsManager } from './themeLiquidDocsManager'; | ||
} from './themeLiquidDocsDownloader'; | ||
export { root } from './utils'; |
@@ -60,13 +60,2 @@ import { expect, describe, it, beforeEach, afterEach, vi } from 'vitest'; | ||
it('should self update once for all docsets', async () => { | ||
vi.mocked(fs.readFile) | ||
.mockImplementationOnce(async () => '{"revision": "1"}') | ||
.mockImplementationOnce(async () => '{"revision": "2"}'); | ||
await Promise.all([manager.filters(), manager.objects(), manager.tags()]); | ||
expect(vi.mocked(downloadFile)).toHaveBeenNthCalledWith(1, 'latest', expect.any(String)); | ||
for (const resource of Resources) { | ||
expect(vi.mocked(downloadFile)).toHaveBeenCalledWith(resource, expect.any(String)); | ||
} | ||
}); | ||
it('should not download remote files if the revision is stable', async () => { | ||
@@ -73,0 +62,0 @@ await Promise.all([manager.filters(), manager.objects(), manager.tags()]); |
@@ -10,2 +10,3 @@ import { | ||
import { ValidateFunction } from 'ajv'; | ||
import path from 'node:path'; | ||
import fs from 'node:fs/promises'; | ||
@@ -18,2 +19,19 @@ import { compileJsonSchema } from './jsonSchemaCompiler'; | ||
function dataRoot() { | ||
if (process.env.WEBPACK_MODE) { | ||
return path.resolve(__dirname, './data'); | ||
} else { | ||
return path.resolve(__dirname, '../data'); | ||
} | ||
} | ||
async function fallback<T>(name: string, defaultValue: T): Promise<T> { | ||
try { | ||
const content = await fs.readFile(path.resolve(dataRoot(), name), 'utf8'); | ||
return JSON.parse(content); | ||
} catch (_) { | ||
return defaultValue; | ||
} | ||
} | ||
export class ThemeLiquidDocsManager implements ThemeDocset, JsonSchemaValidators { | ||
@@ -25,19 +43,25 @@ constructor(private log: Logger = noop) {} | ||
filters = memo(async (): Promise<FilterEntry[]> => { | ||
return this.loadResource('filters', []); | ||
return this.loadResource('filters', await fallback('filters.json', [])); | ||
}); | ||
objects = memo(async (): Promise<ObjectEntry[]> => { | ||
return this.loadResource('objects', []); | ||
return this.loadResource('objects', await fallback('objects.json', [])); | ||
}); | ||
tags = memo(async (): Promise<TagEntry[]> => { | ||
return this.loadResource('tags', []); | ||
return this.loadResource('tags', await fallback('tags.json', [])); | ||
}); | ||
systemTranslations = memo(async (): Promise<Translations> => { | ||
return this.loadResource('shopify_system_translations', {}); | ||
return this.loadResource( | ||
'shopify_system_translations', | ||
await fallback('shopify_system_translations.json', {}), | ||
); | ||
}); | ||
validateSectionSchema = memo(async (): Promise<ValidateFunction> => { | ||
const sectionSchema = await this.loadResource('section_schema', {}); | ||
const sectionSchema = await this.loadResource( | ||
'section_schema', | ||
await fallback('section_schema.json', {}), | ||
); | ||
return compileJsonSchema(sectionSchema); | ||
@@ -54,11 +78,16 @@ }); | ||
setup = memo(async (): Promise<void> => { | ||
if (!(await exists(root))) { | ||
await fs.mkdir(root, { recursive: true }); | ||
} | ||
try { | ||
if (!(await exists(root))) { | ||
await fs.mkdir(root, { recursive: true }); | ||
} | ||
const local = await this.latestRevision(); | ||
await download('latest'); | ||
const remote = await this.latestRevision(); | ||
if (local !== remote) { | ||
await Promise.all(Resources.map((resource) => download(resource))); | ||
const local = await this.latestRevision(); | ||
await download('latest'); | ||
const remote = await this.latestRevision(); | ||
if (local !== remote) { | ||
await Promise.all(Resources.map((resource) => download(resource))); | ||
} | ||
} catch (error) { | ||
if (error instanceof Error) this.log(error.message); | ||
return; | ||
} | ||
@@ -65,0 +94,0 @@ }); |
@@ -10,8 +10,8 @@ import envPaths from 'env-paths'; | ||
export function download(file: Resource | 'latest') { | ||
return downloadFile(file, root); | ||
export function download(file: Resource | 'latest', destination: string = root) { | ||
return downloadFile(file, destination); | ||
} | ||
export function filePath(file: Resource | 'latest') { | ||
return path.join(root, `${file}.json`); | ||
export function filePath(file: Resource | 'latest', destination: string = root) { | ||
return path.join(destination, `${file}.json`); | ||
} | ||
@@ -18,0 +18,0 @@ |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
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
1220332
33
30178
4
1