Skip to content
Merged
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
b112c9a
chore: add Backstage yarn plugin to prep for upgrade
Parkreiner Oct 22, 2025
b222d3c
docs: add comment about new gitignore settings
Parkreiner Oct 22, 2025
076c1f5
fix: run 'yarn install' and save state to branch
Parkreiner Oct 22, 2025
7daf373
chore: try updating more stuff
Parkreiner Oct 23, 2025
dcc9db8
chore: clean up backend package to resemble NBS from fresh install
Parkreiner Oct 24, 2025
5734e85
docs: add missing comment to app-config
Parkreiner Oct 24, 2025
036a2a3
chore: clean up backend package further
Parkreiner Oct 24, 2025
8585e32
fix: remove typo in app-config
Parkreiner Oct 24, 2025
9143e32
refactor: switch to prop for sign in page
Parkreiner Oct 24, 2025
9ca210d
chore: get initial GH auth flow working
Parkreiner Oct 24, 2025
f49d43f
chore: remove deprecated backend packages from package.json
Parkreiner Oct 24, 2025
1d55634
chore: more config clean up
Parkreiner Oct 24, 2025
0eca678
fix: update .gitignore
Parkreiner Oct 24, 2025
7cdd435
chore: add package.json comment
Parkreiner Oct 24, 2025
9820ad2
chore: add more comments
Parkreiner Oct 24, 2025
3af5c2d
chore: add note about coder plugin
Parkreiner Oct 24, 2025
87bc826
docs: add more code snippets
Parkreiner Oct 24, 2025
a2d7d39
refactor: migrate backend coder plugin to NBS
Parkreiner Oct 24, 2025
73650f9
chore: add in example data used by newer scaffolded apps
Parkreiner Oct 24, 2025
78bf0d2
fix: improve logging granularity for coder backend plugin
Parkreiner Oct 24, 2025
c2f66bf
fix: revert logging change
Parkreiner Oct 24, 2025
b960770
wip: commit progress on devcontainers-backend conversion
Parkreiner Oct 25, 2025
fd60848
wip: consolidate temp package back into main one
Parkreiner Oct 25, 2025
141fdc6
chore: add devcontainers-backend to the sample app
Parkreiner Oct 25, 2025
d035fa0
fix: resolve version mismatch in package.json
Parkreiner Oct 25, 2025
e1405db
chore: update all files at root of directory
Parkreiner Oct 25, 2025
640860a
fix: revert accidental change to devcontainers README
Parkreiner Oct 25, 2025
ae42291
chore: update basic frontend files
Parkreiner Oct 25, 2025
f6c7817
chore: update rendering output for app directory
Parkreiner Oct 25, 2025
afbc8e9
chore: update Root component
Parkreiner Oct 25, 2025
b24f648
chore: update EntityPage
Parkreiner Oct 25, 2025
e19aa8f
fix: make sure kubernetes config is null
Parkreiner Oct 25, 2025
0bf1ff7
fix: update App page to use newer APIs
Parkreiner Oct 25, 2025
d4d657c
fix: remove fallback values for .env
Parkreiner Oct 25, 2025
5fbed3a
fix: add back missing themes for legacy MUI code
Parkreiner Oct 25, 2025
59152e0
chore: update react imports for devcontainers-frontend
Parkreiner Oct 25, 2025
02eeaad
fix: add missing dependency for devcontainers backend plugin
Parkreiner Oct 25, 2025
63f1a2c
chore: remove all React imports from project
Parkreiner Oct 25, 2025
b085eb2
fix: silence warning about package type mismatch
Parkreiner Oct 25, 2025
9998deb
refactor: clean up kludge
Parkreiner Oct 26, 2025
030974f
fix: format two yaml files
Parkreiner Oct 27, 2025
bbafac8
feat: migrate Coder plugin to Backstage NBS with OAuth integration
DevelopmentCats Oct 29, 2025
c0eae22
feat: integrate Coder OAuth2 provider with Backstage NBS
DevelopmentCats Oct 30, 2025
4bb7b8e
feat: resolve remaining linting and test issues.
DevelopmentCats Oct 30, 2025
7b97f89
fix: re-include Yarn releases directory in .gitignore
DevelopmentCats Oct 30, 2025
9f0d873
chore: yarn prettier
DevelopmentCats Oct 30, 2025
5724328
chore: update dependencies and versions
DevelopmentCats Oct 30, 2025
569e5eb
chore: simplify build step for devcontainers-react plugin
DevelopmentCats Oct 30, 2025
1dcf227
chore: re-order build step
DevelopmentCats Oct 30, 2025
7bd00f9
chore: resolve remaining blocking issues
DevelopmentCats Oct 30, 2025
edf9d2a
chore: update yarn version command in CI workflow
DevelopmentCats Oct 30, 2025
99ee0e4
chore: update versioning command in CI workflow to use npm
DevelopmentCats Oct 31, 2025
9257168
chore: modify versioning in CI workflow to set package version based …
DevelopmentCats Oct 31, 2025
5c4e2e5
chore: add pluginId and pluginPackages to backstage plugin configurat…
DevelopmentCats Oct 31, 2025
4b98538
chore: update CI workflow to pack plugin with custom output filename
DevelopmentCats Oct 31, 2025
d6973b4
chore: add configApi to OAuth2 provider configuration
DevelopmentCats Oct 31, 2025
e4e5b3b
chore: update README and CI workflow for plugin release tagging
DevelopmentCats Oct 31, 2025
afba842
chore: yarn prettier
DevelopmentCats Oct 31, 2025
e212beb
chore: clean up whitespace in release workflow
DevelopmentCats Oct 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
module.exports = {
root: true,
rules: {
// React 17+ JSX transform doesn't require React to be in scope
'react/react-in-jsx-scope': 'off',
},
};
29 changes: 23 additions & 6 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
name: Release

# This workflow will draft a release for a plugin when tagged. The tag format
# is <name>/v<version> without the backstage-plugin- prefix, e.g. coder/v0.0.0
# This workflow will draft a release for a plugin when tagged. The tag format
# is <plugin-directory>/v<version> where plugin-directory is the exact directory
# name under plugins/, e.g.:
# - backstage-plugin-coder/v0.0.0
# - auth-backend-module-coder-provider/v0.0.0
# - backstage-plugin-devcontainers-backend/v0.0.0

on:
push:
Expand All @@ -20,19 +24,32 @@ jobs:
plugin: ${{ steps.split.outputs.plugin }}
version: ${{ steps.split.outputs.version }}
steps:
- uses: actions/checkout@v4
- env:
TAG: ${{ github.ref_name }}
id: split
run: |
parts=(${TAG//\/v/ })
echo "plugin=${parts[0]}" >> $GITHUB_OUTPUT
echo "version=${parts[1]}" >> $GITHUB_OUTPUT
PLUGIN_NAME="${parts[0]}"
VERSION="${parts[1]}"

if [[ ! -d "plugins/${PLUGIN_NAME}" ]]; then
echo "Error: Plugin directory 'plugins/${PLUGIN_NAME}' not found"
echo "Tag should match the exact directory name in plugins/"
exit 1
fi

echo "plugin=${PLUGIN_NAME}" >> $GITHUB_OUTPUT
echo "version=${VERSION}" >> $GITHUB_OUTPUT

echo "Plugin: ${PLUGIN_NAME}"
echo "Version: ${VERSION}"
plugin:
needs: split-tag
runs-on: ubuntu-latest
defaults:
run:
working-directory: plugins/backstage-plugin-${{ needs.split-tag.outputs.plugin }}
working-directory: plugins/${{ needs.split-tag.outputs.plugin }}
name: ${{ needs.split-tag.outputs.plugin }} v${{ needs.split-tag.outputs.version }}
steps:
- uses: actions/checkout@v4
Expand All @@ -51,4 +68,4 @@ jobs:
- uses: softprops/action-gh-release@v2
with:
draft: true
files: plugins/backstage-plugin-${{ needs.split-tag.outputs.plugin }}/*.tgz
files: plugins/${{ needs.split-tag.outputs.plugin }}/*.tgz
33 changes: 23 additions & 10 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,22 @@ jobs:
id: filter
with:
filters: |
coder:
backstage-plugin-coder:
- ".github/workflows/test.yaml"
- "yarn.lock"
- "plugins/backstage-plugin-coder/**"
devcontainers-backend:
backstage-plugin-devcontainers-backend:
- ".github/workflows/test.yaml"
- "yarn.lock"
- "plugins/backstage-plugin-devcontainers-backend/**"
devcontainers-react:
backstage-plugin-devcontainers-react:
- ".github/workflows/test.yaml"
- "yarn.lock"
- "plugins/backstage-plugin-devcontainers-react/**"
auth-backend-module-coder-provider:
- ".github/workflows/test.yaml"
- "yarn.lock"
- "plugins/auth-backend-module-coder-provider/**"
plugin:
needs: changes
if: ${{ needs.changes.outputs.plugins != '' && toJson(fromJson(needs.changes.outputs.plugins)) != '[]' }}
Expand All @@ -51,7 +55,7 @@ jobs:
name: ${{ matrix.plugin }}
defaults:
run:
working-directory: plugins/backstage-plugin-${{ matrix.plugin }}
working-directory: plugins/${{ matrix.plugin }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand All @@ -60,7 +64,7 @@ jobs:
cache: yarn
- run: yarn install --frozen-lockfile
# The Prettier command is in the root package.json.
- run: yarn prettier --check plugins/backstage-plugin-${{ matrix.plugin }}
- run: yarn prettier --check plugins/${{ matrix.plugin }}
id: fmt
working-directory: .
- run: yarn lint
Expand All @@ -73,20 +77,29 @@ jobs:
- run: yarn test
id: test
if: success() || failure()
# Must run tsc first to generate the .d.ts files.
- run: yarn tsc && yarn build
- run: yarn tsc
working-directory: .
if: success() || failure()
# Build the plugin
- run: yarn build
id: build
if: success() || failure()
# Version it with the SHA and upload to the run as an artifact in case
# someone needs to download it for testing.
- run: yarn version --new-version "0.0.0-devel+$GITHUB_SHA"
- name: Set development version
id: version
- run: yarn pack
run: |
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
node -e "const fs=require('fs'); const pkg=JSON.parse(fs.readFileSync('package.json')); pkg.version='dev-${SHORT_SHA}'; fs.writeFileSync('package.json', JSON.stringify(pkg,null,2)+'\n');"
echo "Set version to dev-${SHORT_SHA}"
- name: Pack plugin
id: pack
run: yarn pack --out '%s-%v.tgz'
- uses: actions/upload-artifact@v4
id: upload
with:
name: ${{ matrix.plugin }}
path: plugins/backstage-plugin-${{ matrix.plugin }}/*.tgz
path: plugins/${{ matrix.plugin }}/*.tgz
# Since we continued on failures above, fail now if there were errors. We
# allow skipped jobs to pass, but not failed or cancelled jobs.
- name: Check required
Expand Down
20 changes: 13 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,27 @@ logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Coverage directory generated when running tests with coverage
coverage

# Dependencies
node_modules/

# Yarn 3 files
# Yarn files
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
# This is skipped because we specify the Yarn version in the root package.json
!.yarn/releases
# Important that we re-include the plugins directory because we need Backstage's
# official Yarn plugin to simplify managing dependencies for each Backstage
# release. The package.json files are updated to include the special
# "backstage:^" value for version numbers, which will break without the plugin
!.yarn/plugins
!.yarn/patches
!.yarn/sdks
!.yarn/versions

# Node version directives
.nvmrc

# dotenv environment variables file
.env
.env.test
Expand All @@ -52,3 +53,8 @@ site

# E2E test reports
e2e-test-report/

# Cache
.cache/
# Local configuration overrides (contains secrets)
app-config.local.yaml
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.19.0
20.19.0
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.19.0
3 changes: 1 addition & 2 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ dist
dist-types
coverage
.vscode
.coder.yaml
app-config.local.yaml
.coder.yaml
9 changes: 9 additions & 0 deletions .yarn/plugins/@yarnpkg/plugin-backstage.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* eslint-disable */
//prettier-ignore
module.exports = {
name: "@yarnpkg/plugin-backstage",
factory: function (require) {
"use strict";var plugin=(()=>{var ee=Object.create;var R=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var te=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,ne=Object.prototype.hasOwnProperty;var f=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(r,t)=>(typeof require<"u"?require:r)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var se=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports),ae=(e,r)=>{for(var t in r)R(e,t,{get:r[t],enumerable:!0})},M=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of te(r))!ne.call(e,o)&&o!==t&&R(e,o,{get:()=>r[o],enumerable:!(n=re(r,o))||n.enumerable});return e};var S=(e,r,t)=>(t=e!=null?ee(oe(e)):{},M(r||!e||!e.__esModule?R(t,"default",{value:e,enumerable:!0}):t,e)),ie=e=>M(R({},"__esModule",{value:!0}),e);var H=se((Ae,z)=>{"use strict";var $=class e extends Error{constructor(r){super(e._prepareSuperMessage(r)),Object.defineProperty(this,"name",{value:"NonError",configurable:!0,writable:!0}),Error.captureStackTrace&&Error.captureStackTrace(this,e)}static _prepareSuperMessage(r){try{return JSON.stringify(r)}catch{return String(r)}}},fe=[{property:"name",enumerable:!1},{property:"message",enumerable:!1},{property:"stack",enumerable:!1},{property:"code",enumerable:!0}],D=Symbol(".toJSON called"),le=e=>{e[D]=!0;let r=e.toJSON();return delete e[D],r},T=({from:e,seen:r,to_:t,forceEnumerable:n,maxDepth:o,depth:a})=>{let i=t||(Array.isArray(e)?[]:{});if(r.push(e),a>=o)return i;if(typeof e.toJSON=="function"&&e[D]!==!0)return le(e);for(let[s,p]of Object.entries(e)){if(typeof Buffer=="function"&&Buffer.isBuffer(p)){i[s]="[object Buffer]";continue}if(typeof p!="function"){if(!p||typeof p!="object"){i[s]=p;continue}if(!r.includes(e[s])){a++,i[s]=T({from:e[s],seen:r.slice(),forceEnumerable:n,maxDepth:o,depth:a});continue}i[s]="[Circular]"}}for(let{property:s,enumerable:p}of fe)typeof e[s]=="string"&&Object.defineProperty(i,s,{value:e[s],enumerable:n?!0:p,configurable:!0,writable:!0});return i},ge=(e,r={})=>{let{maxDepth:t=Number.POSITIVE_INFINITY}=r;return typeof e=="object"&&e!==null?T({from:e,seen:[],forceEnumerable:!0,maxDepth:t,depth:0}):typeof e=="function"?`[Function: ${e.name||"anonymous"}]`:e},me=(e,r={})=>{let{maxDepth:t=Number.POSITIVE_INFINITY}=r;if(e instanceof Error)return e;if(typeof e=="object"&&e!==null&&!Array.isArray(e)){let n=new Error;return T({from:e,seen:[],to_:n,maxDepth:t,depth:0}),n}return new $(e)};z.exports={serializeError:ge,deserializeError:me}});var ve={};ae(ve,{default:()=>xe});var P=f("@yarnpkg/core");var E=f("@yarnpkg/core");var U=S(f("assert")),q=f("semver"),v=f("@yarnpkg/fslib");var d=S(f("fs")),l=f("path");function _(e,r){let t=e;for(let n=0;n<1e3;n++){let o=(0,l.resolve)(t,"package.json");if(d.default.existsSync(o)&&r(o))return t;let i=(0,l.dirname)(t);if(i===t)return;t=i}throw new Error(`Iteration limit reached when searching for root package.json at ${e}`)}function ce(e){let r=_(e,()=>!0);if(!r)throw new Error(`No package.json found while searching for package root of ${e}`);return r}function pe(e){if(!d.default.existsSync((0,l.resolve)(e,"src")))throw new Error("Tried to access monorepo package root dir outside of Backstage repository");return(0,l.resolve)(e,"../..")}function O(e){let r=ce(e),t=d.default.realpathSync(process.cwd()).replace(/^[a-z]:/,s=>s.toLocaleUpperCase("en-US")),n="",o=()=>(n||(n=pe(r)),n),a="",i=()=>(a||(a=_(t,s=>{try{let p=d.default.readFileSync(s,"utf8");return!!JSON.parse(p).workspaces}catch(p){throw new Error(`Failed to parse package.json file while searching for root, ${p}`)}})??t),a);return{ownDir:r,get ownRoot(){return o()},targetDir:t,get targetRoot(){return i()},resolveOwn:(...s)=>(0,l.resolve)(r,...s),resolveOwnRoot:(...s)=>(0,l.resolve)(o(),...s),resolveTarget:(...s)=>(0,l.resolve)(t,...s),resolveTargetRoot:(...s)=>(0,l.resolve)(i(),...s)}}var B="backstage.json";function u(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let r=e;return!(typeof r.name!="string"||r.name===""||typeof r.message!="string")}var J=S(H());function G(e){if(u(e)){let r=String(e);return r!=="[object Object]"?r:`${e.name}: ${e.message}`}return`unknown error '${e}'`}var x=class extends Error{cause;constructor(r,t){let n=r;if(t!==void 0){let o=G(t);n?n+=`; caused by ${o}`:n=`caused by ${o}`}super(n),Error.captureStackTrace?.(this,this.constructor),(!this.name||this.name==="Error")&&this.constructor.name!=="Error"&&(this.name=this.constructor.name),this.cause=u(t)?t:void 0}};var k=class extends x{constructor(r,t){super(r,t),this.name=u(t)?t.name:"Error"}};var K=e=>{let r=!1,t;return()=>(r||(t=e(),r=!0),t)};var y=f("@yarnpkg/fslib");var Y=()=>y.npath.toPortablePath(O(y.npath.fromPortablePath(y.ppath.cwd())).targetRoot);var h=K(()=>{let e=v.ppath.join(Y(),B),r=null;try{let t=v.xfs.readJsonSync(e).version;(0,U.default)(t!==void 0,"Version field is missing"),r=(0,q.valid)(t),(0,U.default)(r!==null,"Version exists but is not valid semver")}catch(t){throw new k("Valid version string not found in backstage.json",t)}return r});var w=f("@yarnpkg/core"),Q=f("@yarnpkg/fslib");var ue="https://versions.backstage.io",de="https://raw.githubusercontent.com/backstage/versions/main";function ke(e,r){return new Promise((t,n)=>{let o=setTimeout(()=>{r.aborted||t()},e);r.addEventListener("abort",()=>{clearTimeout(o),n(new Error("Aborted"))})})}async function ye(e,r,t){let n=new AbortController,o=new AbortController,a=e(n.signal).then(s=>(o.abort(),s)),i=ke(t,o.signal).then(()=>r(o.signal)).then(s=>(n.abort(),s));return Promise.any([a,i]).catch(()=>a)}async function A(e){let r=encodeURIComponent(e.version),t=e.fetch??fetch,n=e.versionsBaseUrl??ue,o=e.gitHubRawBaseUrl??de,a=await ye(i=>t(`${n}/v1/releases/${r}/manifest.json`,{signal:i}),i=>t(`${o}/v1/releases/${r}/manifest.json`,{signal:i}),500);if(a.status===404)throw new Error(`No release found for ${e.version} version`);if(a.status!==200)throw new Error(`Unexpected response status ${a.status} when fetching release from ${a.url}.`);return a.json()}var c="backstage:";var j=f("process"),m=async(e,r)=>{let t=w.structUtils.stringifyIdent(e),n=w.structUtils.parseRange(e.range);if(n.protocol!==c)throw new Error(`Unsupported version protocol in version range "${e.range}" for package ${t}`);if(n.selector!=="^")throw new Error(`Unexpected version selector "${n.selector}" for package ${t}`);let o=h(),a=j.env.BACKSTAGE_MANIFEST_FILE,s=(a?await Q.xfs.readJsonSync(a):await A({version:o,versionsBaseUrl:j.env.BACKSTAGE_VERSIONS_BASE_URL,fetch:async p=>{let F=await w.httpUtils.get(p,{configuration:r,jsonResponse:!0});return{status:200,url:p,json:()=>F}}})).packages.find(p=>p.name===t);if(!s)throw new Error(`Package ${t} not found in manifest for Backstage v${o}. This means the specified package is not included in this Backstage release. This may imply the package has been replaced with an alternative - please review the documentation for the package. If you need to continue using this package, it will be necessary to switch to manually managing its version.`);return s.version};var he=e=>E.structUtils.parseRange(e).protocol===c,we=(e,r,t)=>e!=="dependencies"?e:t.manifest.ensureDependencyMeta(E.structUtils.makeDescriptor(r,"unknown")).optional?"optionalDependencies":e,L=async(e,r)=>{for(let t of["dependencies","devDependencies"]){let n=Array.from(e.manifest.getForScope(t).values()).filter(o=>o.range.startsWith(c));for(let o of n){let a=E.structUtils.stringifyIdent(o);if(E.structUtils.parseRange(o.range).selector!=="^")throw new Error(`Unexpected version range "${o.range}" for dependency on "${a}"`);let s=we(t,o,e);r[s][a]=`^${await m(o,e.project.configuration)}`}}if(["dependencies","devDependencies","optionalDependencies"].some(t=>Object.values(r[t]??{}).some(he)))throw new Error(`Failed to replace all "backstage:" ranges in manifest for ${r.name}`)};var C=f("@yarnpkg/core");var V=async(e,r)=>{let t=C.structUtils.parseRange(e.range);if(t.protocol!==c)return e;if(t.selector!=="^")throw new Error(`Invalid backstage: version range found: ${e.range}`);return C.structUtils.bindDescriptor(e,{backstage:h(),npm:await m(e,r.configuration)})};var X=f("@yarnpkg/core");var N=async(e,r,t,n)=>{let o=X.structUtils.parseRange(t.range);if(t.scope==="backstage"&&o.protocol!==c){let a=t.range;try{t.range=`${c}^`,await m(t,e.project.configuration),console.info(`Setting ${t.scope}/${t.name} to ${c}^`)}catch{t.range=a}}};var Z=f("@yarnpkg/core");var I=async(e,r,t,n)=>{let o=Z.structUtils.parseRange(n.range);n.scope==="backstage"&&o.protocol!==c&&console.warn(`${n.name} should be set to "${c}^" instead of "${n.range}". Make sure this change is intentional and not a mistake.`)};var g=f("@yarnpkg/core"),W=f("@yarnpkg/plugin-npm");var b=class e{static protocol=c;supportsDescriptor=r=>r.range.startsWith(e.protocol);async getCandidates(r,t,n){let o=g.structUtils.parseRange(r.range).params?.npm;if(!o||Array.isArray(o))throw new Error(`Missing npm parameter on backstage: range "${r.range}"`);return new W.NpmSemverResolver().getCandidates(g.structUtils.makeDescriptor(r,`npm:^${o}`),t,n)}getResolutionDependencies(r){let t=g.structUtils.parseRange(r.range).params?.npm;if(!t)throw new Error(`Missing npm parameter on backstage: range "${r.range}".`);return{[g.structUtils.stringifyIdent(r)]:g.structUtils.makeDescriptor(r,`npm:^${t}`)}}async getSatisfying(r,t,n,o){let a=r,i=g.structUtils.parseRange(a.range);if(i.protocol===c){let s=i.params?.npm;a=g.structUtils.makeDescriptor(r,`npm:^${s}`)}return new W.NpmSemverResolver().getSatisfying(a,t,n,o)}bindDescriptor=r=>r;supportsLocator=()=>!1;shouldPersistResolution=()=>{throw new Error("Unreachable: BackstageNpmResolver should never persist resolution as it uses npm: protocol")};resolve=async()=>{throw new Error("Unreachable: BackstageNpmResolver should never resolve as it uses npm: protocol")}};var Ee="\x1B[31;1m",be="\x1B[0m";P.semverUtils.satisfiesWithPrereleases(P.YarnVersion,"^4.1.1")||(console.error(),console.error(`${Ee}Unsupported yarn version${be}: The Backstage yarn plugin only works with yarn ^4.1.1. Please upgrade yarn, or remove this plugin with "yarn plugin remove @yarnpkg/plugin-backstage".`),console.error());var Re={hooks:{afterWorkspaceDependencyAddition:N,afterWorkspaceDependencyReplacement:I,reduceDependency:V,beforeWorkspacePacking:L},resolvers:[b]},xe=Re;return ie(ve);})();
return plugin;
}
};
Loading
Loading