diff --git a/.changeset/dull-moles-deny.md b/.changeset/dull-moles-deny.md new file mode 100644 index 000000000..ed98b7ef4 --- /dev/null +++ b/.changeset/dull-moles-deny.md @@ -0,0 +1,5 @@ +--- +'@shopify/theme-check-docs-updater': minor +--- + +Add `theme-docs dependencies` command diff --git a/packages/theme-check-docs-updater/package.json b/packages/theme-check-docs-updater/package.json index a4f159d5f..27caee101 100644 --- a/packages/theme-check-docs-updater/package.json +++ b/packages/theme-check-docs-updater/package.json @@ -19,13 +19,13 @@ "@shopify:registry": "https://registry.npmjs.org" }, "bin": { - "theme-docs": "./scripts/cli.js" + "theme-docs": "./dist/cli.js" }, "scripts": { "build": "yarn build:ts", "build:ci": "yarn build", "build:ts": "tsc -b tsconfig.build.json", - "postbuild": "node scripts/cli.js download data", + "postbuild": "chmod u+x dist/cli.js && node dist/cli.js download data", "test": "vitest", "type-check": "tsc --noEmit" }, diff --git a/packages/theme-check-docs-updater/scripts/cli.js b/packages/theme-check-docs-updater/scripts/cli.js deleted file mode 100755 index fa6597e0e..000000000 --- a/packages/theme-check-docs-updater/scripts/cli.js +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env node - -const path = require('path'); -const fs = require('fs'); -const { downloadThemeLiquidDocs, root } = require(path.resolve(__dirname, '../dist')); - -// Get the command line arguments -const args = process.argv.slice(2); - -// Check if a command was provided -if (args.length === 0) { - console.log(` -Please provide a command. - -Usage: - download \t\tDownloads all docsets and JSON Schemas to the specified directory. - root \tPrints the default docsets root directory. - clear-cache \tClears the default docsets root directory. -`); - process.exit(1); -} - -// Handle the command -switch (args[0]) { - case 'download': - if (args.length > 2) { - console.log('Please provide a directory to download docs into.'); - process.exit(1); - } - console.log('Downloading docs...'); - - downloadThemeLiquidDocs(args[1], console.error.bind(console)); - - break; - - case 'root': - console.log(root); - break; - - case 'clear-cache': - console.log(`Removing '${root}'`); - fs.rmSync(root, { recursive: true }); - break; - - default: - console.log(`Unknown command: ${args[0]}`); - process.exit(1); -} diff --git a/packages/theme-check-docs-updater/src/cli.ts b/packages/theme-check-docs-updater/src/cli.ts new file mode 100755 index 000000000..b79b487f2 --- /dev/null +++ b/packages/theme-check-docs-updater/src/cli.ts @@ -0,0 +1,74 @@ +#!/usr/bin/env node + +import fs from 'node:fs'; +import { downloadThemeLiquidDocs, root, ThemeLiquidDocsManager } from '.'; + +// Get the command line arguments +const args = process.argv.slice(2); + +// Check if a command was provided +if (args.length === 0) { + console.log(` +Please provide a command. + +Usage: + download \t\tDownloads all docsets and JSON Schemas to the specified directory. + dependencies \t\tPrints the up to date theme dependencies. + root \tPrints the default docsets root directory. + clear-cache \tClears the default docsets root directory. +`); + process.exit(1); +} + +async function main() { + // Handle the command + switch (args[0]) { + case 'download': + if (args.length > 2) { + console.log('Please provide a directory to download docs into.'); + process.exit(1); + } + console.log('Downloading docs...'); + + downloadThemeLiquidDocs(args[1], console.error.bind(console)); + + break; + + case 'dependencies': + // This command is used to print the current state of the docs. + // It's a bit like what the webpack build of the fallback does in the browser VS Code extension. + const docsManager = new ThemeLiquidDocsManager(); + const [tags, filters, objects, systemTranslations, schemas] = await Promise.all([ + docsManager.tags(), + docsManager.filters(), + docsManager.objects(), + docsManager.systemTranslations(), + docsManager.schemas('theme'), // assuming we want the theme JSON schema validation + ]); + console.log( + JSON.stringify({ + tags, + filters, + objects, + systemTranslations, + schemas, + }), + ); + break; + + case 'root': + console.log(root); + break; + + case 'clear-cache': + console.log(`Removing '${root}'`); + fs.rmSync(root, { recursive: true }); + break; + + default: + console.log(`Unknown command: ${args[0]}`); + process.exit(1); + } +} + +main(); diff --git a/packages/vscode-extension/src/browser/ThemeDocset.ts b/packages/vscode-extension/src/browser/ThemeDocset.ts new file mode 100644 index 000000000..465252948 --- /dev/null +++ b/packages/vscode-extension/src/browser/ThemeDocset.ts @@ -0,0 +1,63 @@ +import { memo } from '@shopify/theme-check-common'; +import { Dependencies } from '@shopify/theme-language-server-browser'; +import { Connection } from 'vscode-languageserver/browser'; + +/** + * These are replaced at build time by the contents of + * @shopify/theme-check-docs-updater's DocsManager + */ +declare global { + export const WEBPACK_TAGS: any[]; + export const WEBPACK_FILTERS: any[]; + export const WEBPACK_OBJECTS: any[]; + export const WEBPACK_SYSTEM_TRANSLATIONS: any; + export const WEBPACK_SCHEMAS: any; +} + +const tags = WEBPACK_TAGS; +const filters = WEBPACK_FILTERS; +const objects = WEBPACK_OBJECTS; +const systemTranslations = WEBPACK_SYSTEM_TRANSLATIONS; +const schemas = WEBPACK_SCHEMAS; + +type ThemeDocset = Dependencies['themeDocset']; +type JsonValidationSet = Dependencies['jsonValidationSet']; + +const fetchDeps = memo(async () => { + return fetch('https://vs-code-for-web.shop.dev/deps.json').then((response) => { + if (!response.ok) { + console.error(response); + throw new Error(`Failed to fetch dependencies: ${response.statusText}`); + } + return response.json(); + }); +}); + +export class ThemeDocsetManager implements ThemeDocset, JsonValidationSet { + constructor(private connection: Connection) {} + + // Liquid documentation + filters = memo(async () => this.fetchUpdatedData('filters', filters)); + tags = memo(async () => this.fetchUpdatedData('tags', tags)); + objects = memo(async () => this.fetchUpdatedData('objects', objects)); + liquidDrops = memo(async () => this.fetchUpdatedData('objects', objects)); + + // prettier-ignore + systemTranslations = memo(async () => this.fetchUpdatedData('systemTranslations', systemTranslations)); + + // JSON validation data + schemas = memo(async () => this.fetchUpdatedData('schemas', schemas)); + + fetchUpdatedData = async ( + dependency: 'filters' | 'tags' | 'objects' | 'systemTranslations' | 'schemas', + fallback: T, + ): Promise => { + return fetchDeps() + .then((deps) => deps[dependency] ?? fallback) + .then((data) => { + console.error(`data received! ${dependency}`, data); + return data as T; + }) + .catch(() => fallback); + }; +} diff --git a/packages/vscode-extension/src/browser/server.ts b/packages/vscode-extension/src/browser/server.ts index 958d0a225..d6ad6b3c2 100644 --- a/packages/vscode-extension/src/browser/server.ts +++ b/packages/vscode-extension/src/browser/server.ts @@ -6,28 +6,12 @@ import { startServer, } from '@shopify/theme-language-server-browser'; import { VsCodeFileSystem } from '../common/VsCodeFileSystem'; - -/** - * These are replaced at build time by the contents of - * @shopify/theme-check-docs-updater's DocsManager - */ -declare global { - export const WEBPACK_TAGS: any[]; - export const WEBPACK_FILTERS: any[]; - export const WEBPACK_OBJECTS: any[]; - export const WEBPACK_SYSTEM_TRANSLATIONS: any; - export const WEBPACK_SCHEMAS: any; -} - -const tags = WEBPACK_TAGS; -const filters = WEBPACK_FILTERS; -const objects = WEBPACK_OBJECTS; -const systemTranslations = WEBPACK_SYSTEM_TRANSLATIONS; -const schemas = WEBPACK_SCHEMAS; +import { ThemeDocsetManager } from './ThemeDocset'; const worker = self as any as Worker; const connection = getConnection(worker); const fileSystem = new VsCodeFileSystem(connection, {}); +const themeDocset = new ThemeDocsetManager(connection); const dependencies: Dependencies = { fs: fileSystem, log: console.info.bind(console), @@ -45,16 +29,8 @@ const dependencies: Dependencies = { rootUri, }; }, - themeDocset: { - filters: async () => filters, - objects: async () => objects, - liquidDrops: async () => objects, - tags: async () => tags, - systemTranslations: async () => systemTranslations, - }, - jsonValidationSet: { - schemas: async () => schemas, - }, + themeDocset: themeDocset, + jsonValidationSet: themeDocset, }; startServer(worker, dependencies, connection);