diff --git a/goldens/vscode-extension/BUILD.bazel b/goldens/vscode-extension/BUILD.bazel new file mode 100644 index 00000000000..a937a549d55 --- /dev/null +++ b/goldens/vscode-extension/BUILD.bazel @@ -0,0 +1 @@ +exports_files(["vsix_package_contents.txt"]) diff --git a/goldens/vscode-extension/vsix_package_contents.txt b/goldens/vscode-extension/vsix_package_contents.txt new file mode 100644 index 00000000000..11c1cb650ee --- /dev/null +++ b/goldens/vscode-extension/vsix_package_contents.txt @@ -0,0 +1,27 @@ +CHANGELOG.md +README.md +angular.png +index.js +node_modules/@angular/language-service/api.d.ts +node_modules/@angular/language-service/api_bundle.js +node_modules/@angular/language-service/bundles/language-service.js +node_modules/@angular/language-service/factory_bundle.js +node_modules/@angular/language-service/index.d.ts +node_modules/@angular/language-service/index.js +node_modules/@angular/language-service/package.json +node_modules/@angular/language-service/plugin-factory.d.ts +node_modules/typescript +package.json +server/README.md +server/bin/ngserver +server/index.js +server/package.json +syntaxes/expression.json +syntaxes/host-object-literal.json +syntaxes/inline-styles.json +syntaxes/inline-template.json +syntaxes/let-declaration.json +syntaxes/template-blocks.json +syntaxes/template-tag.json +syntaxes/template.json +syntaxes/tsconfig.json \ No newline at end of file diff --git a/vscode-ng-language-service/BUILD.bazel b/vscode-ng-language-service/BUILD.bazel index fbd4f5f75f5..7ad760e0987 100644 --- a/vscode-ng-language-service/BUILD.bazel +++ b/vscode-ng-language-service/BUILD.bazel @@ -1,5 +1,6 @@ load("@aspect_bazel_lib//lib:expand_template.bzl", "expand_template_rule") -load("@aspect_rules_js//js:defs.bzl", "js_library") +load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_file") +load("@aspect_rules_js//js:defs.bzl", "js_library", "js_run_binary") load("@aspect_rules_js//npm:defs.bzl", "npm_package") load("@aspect_rules_ts//ts:defs.bzl", "ts_config") load("@npm//:defs.bzl", "npm_link_all_packages") @@ -104,3 +105,20 @@ npm_package( ], visibility = ["//vscode-ng-language-service/integration/e2e:__subpackages__"], ) + +js_run_binary( + name = "vsix_contents_golden_file", + srcs = [":vsix_sandbox"], + outs = ["vsix_package_contents.txt"], + args = [ + "$(rootpath vsix_package_contents.txt)", + ], + tool = "//vscode-ng-language-service/tools:vsix_contents_goldens", +) + +write_source_file( + name = "vsix_contents_golden", + check_that_out_file_exists = False, + in_file = ":vsix_contents_golden_file", + out_file = "//goldens/vscode-extension:vsix_package_contents.txt", +) diff --git a/vscode-ng-language-service/tools/BUILD.bazel b/vscode-ng-language-service/tools/BUILD.bazel new file mode 100644 index 00000000000..66e180e9d5d --- /dev/null +++ b/vscode-ng-language-service/tools/BUILD.bazel @@ -0,0 +1,13 @@ +load("@aspect_rules_js//js:defs.bzl", "js_binary") + +js_binary( + name = "vsix_contents_goldens", + data = ["//vscode-ng-language-service:node_modules/@vscode/vsce"], + entry_point = ":vsix_contents_goldens.mjs", + # vsce requires npm on the PATH; we can get this from the Bazel rules_nodejs but it is not + # included by default in rules_js binary rules so we include it here explicitly + include_npm = True, + visibility = [ + "//vscode-ng-language-service:__pkg__", + ], +) diff --git a/vscode-ng-language-service/tools/vsix_contents_goldens.mjs b/vscode-ng-language-service/tools/vsix_contents_goldens.mjs new file mode 100644 index 00000000000..730f5ab69f9 --- /dev/null +++ b/vscode-ng-language-service/tools/vsix_contents_goldens.mjs @@ -0,0 +1,66 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +// tslint:disable:no-console +import {writeFile} from 'node:fs/promises'; +import {exec as nodeExec} from 'node:child_process'; +import {promisify} from 'node:util'; +import {join} from 'node:path'; + +const exec = promisify(nodeExec); +const rootPath = join(import.meta.dirname, '../'); + +async function main(outPath) { + // `vsce ls` needs to run with a CWD of what will be packaged. + // There is no way to provide this via args. + const {stdout, stderr} = await exec( + `node ${join(rootPath, `node_modules/@vscode/vsce/vsce`)} ls`, + { + cwd: join(rootPath, 'vsix_sandbox'), + }, + ); + + if (stderr) { + console.error(stderr); + throw new Error('Failed with error. See above.'); + } + + const paths = stdout.trim().split('\n').filter(Boolean); + const resultSet = new Set(); + + for (const filePath of paths) { + if (filePath.startsWith('node_modules/') && !filePath.includes('@angular')) { + // Regex to capture 'node_modules/' followed by either: + // - A scoped package (e.g., @vscode/vsce) + // - A standard package (e.g., typescript) + // It stops matching before the next slash after the package name. + const match = filePath.match(/^(node_modules\/(?:@[^\/]+\/[^\/]+|[^\/]+))/); + if (match) { + resultSet.add(match[1]); + } + } else { + // Add non-node_modules or @angular/ paths directly + resultSet.add(filePath); + } + } + + await writeFile(outPath, Array.from(resultSet).sort().join('\n')); +} + +const argv = process.argv.slice(2); +if (argv.length !== 1) { + console.error('Must include 1 argument that specifies the output path.'); + process.exit(1); +} + +const [outPath] = argv; + +main(outPath).catch((err) => { + console.error(err); + process.exit(1); +});