@askrjs/cli 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +140 -0
- package/dist/add-DqhqRzBQ.js +555 -0
- package/dist/add-DqhqRzBQ.js.map +1 -0
- package/dist/add.js +3 -0
- package/dist/cli.js +91 -0
- package/dist/cli.js.map +1 -0
- package/dist/create.js +923 -0
- package/dist/create.js.map +1 -0
- package/dist/is-direct-execution-Cdlr-ZUl.js +20 -0
- package/dist/is-direct-execution-Cdlr-ZUl.js.map +1 -0
- package/dist/openapi.js +127 -0
- package/dist/openapi.js.map +1 -0
- package/dist/skills/askr-accessibility/SKILL.md +68 -0
- package/dist/skills/askr-accessibility/agents/openai.yaml +4 -0
- package/dist/skills/askr-agent-execution/SKILL.md +85 -0
- package/dist/skills/askr-agent-execution/agents/openai.yaml +4 -0
- package/dist/skills/askr-agent-workflows/SKILL.md +57 -0
- package/dist/skills/askr-agent-workflows/agents/openai.yaml +4 -0
- package/dist/skills/askr-api-integration/SKILL.md +79 -0
- package/dist/skills/askr-api-integration/agents/openai.yaml +4 -0
- package/dist/skills/askr-app-builder/SKILL.md +99 -0
- package/dist/skills/askr-app-builder/agents/openai.yaml +4 -0
- package/dist/skills/askr-auth-access/SKILL.md +74 -0
- package/dist/skills/askr-auth-access/agents/openai.yaml +4 -0
- package/dist/skills/askr-cli-vite/SKILL.md +76 -0
- package/dist/skills/askr-cli-vite/agents/openai.yaml +4 -0
- package/dist/skills/askr-dashboard-charts/SKILL.md +82 -0
- package/dist/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
- package/dist/skills/askr-design-system/SKILL.md +86 -0
- package/dist/skills/askr-design-system/agents/openai.yaml +4 -0
- package/dist/skills/askr-env-config/SKILL.md +74 -0
- package/dist/skills/askr-env-config/agents/openai.yaml +4 -0
- package/dist/skills/askr-error-loading-empty/SKILL.md +89 -0
- package/dist/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
- package/dist/skills/askr-file-upload-artifacts/SKILL.md +77 -0
- package/dist/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
- package/dist/skills/askr-forms-tables-crud/SKILL.md +98 -0
- package/dist/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
- package/dist/skills/askr-mental-model/SKILL.md +109 -0
- package/dist/skills/askr-mental-model/agents/openai.yaml +4 -0
- package/dist/skills/askr-migration-react/SKILL.md +81 -0
- package/dist/skills/askr-migration-react/agents/openai.yaml +4 -0
- package/dist/skills/askr-observability-debugging/SKILL.md +83 -0
- package/dist/skills/askr-observability-debugging/agents/openai.yaml +4 -0
- package/dist/skills/askr-project-structure/SKILL.md +79 -0
- package/dist/skills/askr-project-structure/agents/openai.yaml +4 -0
- package/dist/skills/askr-query-mutation/SKILL.md +115 -0
- package/dist/skills/askr-query-mutation/agents/openai.yaml +4 -0
- package/dist/skills/askr-realtime-streaming/SKILL.md +76 -0
- package/dist/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
- package/dist/skills/askr-resources-data/SKILL.md +100 -0
- package/dist/skills/askr-resources-data/agents/openai.yaml +4 -0
- package/dist/skills/askr-routing-layouts/SKILL.md +107 -0
- package/dist/skills/askr-routing-layouts/agents/openai.yaml +4 -0
- package/dist/skills/askr-runtime-reactivity/SKILL.md +92 -0
- package/dist/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
- package/dist/skills/askr-ssr-ssg/SKILL.md +76 -0
- package/dist/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
- package/dist/skills/askr-testing-determinism/SKILL.md +75 -0
- package/dist/skills/askr-testing-determinism/agents/openai.yaml +4 -0
- package/dist/skills/askr-theming/SKILL.md +86 -0
- package/dist/skills/askr-theming/agents/openai.yaml +4 -0
- package/dist/skills/askr-ui-composition/SKILL.md +92 -0
- package/dist/skills/askr-ui-composition/agents/openai.yaml +4 -0
- package/dist/skills-Bh0mEhIx.js +682 -0
- package/dist/skills-Bh0mEhIx.js.map +1 -0
- package/dist/skills.js +3 -0
- package/dist/ssg.js +188 -0
- package/dist/ssg.js.map +1 -0
- package/dist/templates/full-stack/AGENTS.md +12 -0
- package/dist/templates/full-stack/README.md +18 -0
- package/dist/templates/full-stack/gitignore.template +4 -0
- package/dist/templates/full-stack/index.html +14 -0
- package/dist/templates/full-stack/package.json +37 -0
- package/dist/templates/full-stack/server.ts +13 -0
- package/dist/templates/full-stack/src/action-authorizations.ts +10 -0
- package/dist/templates/full-stack/src/actions/create-message.ts +10 -0
- package/dist/templates/full-stack/src/i18n.ts +8 -0
- package/dist/templates/full-stack/src/main.tsx +12 -0
- package/dist/templates/full-stack/src/pages/home.tsx +25 -0
- package/dist/templates/full-stack/src/pages/layout.tsx +33 -0
- package/dist/templates/full-stack/src/pages/not-found.tsx +4 -0
- package/dist/templates/full-stack/src/routes.tsx +20 -0
- package/dist/templates/full-stack/src/schemas.ts +11 -0
- package/dist/templates/full-stack/src/server/action-registry.ts +12 -0
- package/dist/templates/full-stack/src/server/actions/create-message.ts +14 -0
- package/dist/templates/full-stack/src/server/app.ts +66 -0
- package/dist/templates/full-stack/src/server/dependencies.ts +55 -0
- package/dist/templates/full-stack/src/server/entry-server.ts +8 -0
- package/dist/templates/full-stack/src/telemetry.ts +4 -0
- package/dist/templates/full-stack/src/vite-server.d.ts +6 -0
- package/dist/templates/full-stack/tests/actions/create-message.test.ts +13 -0
- package/dist/templates/full-stack/tsconfig.json +16 -0
- package/dist/templates/full-stack/vite.config.ts +11 -0
- package/dist/templates/spa/AGENTS.md +60 -0
- package/dist/templates/spa/README.md +96 -0
- package/dist/templates/spa/gitignore.template +16 -0
- package/dist/templates/spa/index.html +13 -0
- package/dist/templates/spa/package.json +35 -0
- package/dist/templates/spa/src/adapters/operations-client.ts +90 -0
- package/dist/templates/spa/src/components/shared/metric-card.tsx +27 -0
- package/dist/templates/spa/src/components/shared/status-badge.tsx +24 -0
- package/dist/templates/spa/src/features/operations/operations.query.ts +9 -0
- package/dist/templates/spa/src/main.tsx +10 -0
- package/dist/templates/spa/src/pages/_layout.tsx +9 -0
- package/dist/templates/spa/src/pages/_routes.tsx +27 -0
- package/dist/templates/spa/src/pages/app/_layout.tsx +94 -0
- package/dist/templates/spa/src/pages/app/_routes.tsx +10 -0
- package/dist/templates/spa/src/pages/app/admin-home.tsx +152 -0
- package/dist/templates/spa/src/pages/app/agent-runs.tsx +93 -0
- package/dist/templates/spa/src/pages/app/settings.tsx +91 -0
- package/dist/templates/spa/src/pages/auth/_layout.tsx +38 -0
- package/dist/templates/spa/src/pages/auth/_routes.tsx +6 -0
- package/dist/templates/spa/src/pages/auth/login.tsx +63 -0
- package/dist/templates/spa/src/pages/not-found.tsx +22 -0
- package/dist/templates/spa/src/pages/public/_layout.tsx +47 -0
- package/dist/templates/spa/src/pages/public/_routes.tsx +6 -0
- package/dist/templates/spa/src/pages/public/home.tsx +143 -0
- package/dist/templates/spa/src/shared/format.ts +12 -0
- package/dist/templates/spa/src/shared/navigation.ts +15 -0
- package/dist/templates/spa/src/styles/components.css +49 -0
- package/dist/templates/spa/src/styles/layout.css +192 -0
- package/dist/templates/spa/src/styles/reset.css +44 -0
- package/dist/templates/spa/src/styles/theme.css +57 -0
- package/dist/templates/spa/src/styles/tokens.css +20 -0
- package/dist/templates/spa/src/styles.css +7 -0
- package/dist/templates/spa/src/styles.d.ts +1 -0
- package/dist/templates/spa/tests/app.test.tsx +37 -0
- package/dist/templates/spa/tests/components/shared.test.tsx +12 -0
- package/dist/templates/spa/tests/resources.test.ts +22 -0
- package/dist/templates/spa/tsconfig.json +20 -0
- package/dist/templates/spa/tsconfig.node.json +10 -0
- package/dist/templates/spa/vite.config.ts +24 -0
- package/dist/templates/spa/vitest.config.ts +17 -0
- package/dist/templates/ssg/AGENTS.md +55 -0
- package/dist/templates/ssg/README.md +39 -0
- package/dist/templates/ssg/gitignore.template +17 -0
- package/dist/templates/ssg/index.html +13 -0
- package/dist/templates/ssg/package.json +35 -0
- package/dist/templates/ssg/src/app.tsx +14 -0
- package/dist/templates/ssg/src/components/badge.tsx +3 -0
- package/dist/templates/ssg/src/components/counter.tsx +30 -0
- package/dist/templates/ssg/src/components/site-shell.tsx +111 -0
- package/dist/templates/ssg/src/jsx.d.ts +23 -0
- package/dist/templates/ssg/src/main.tsx +8 -0
- package/dist/templates/ssg/src/pages/about.tsx +82 -0
- package/dist/templates/ssg/src/pages/content.tsx +63 -0
- package/dist/templates/ssg/src/pages/example.tsx +97 -0
- package/dist/templates/ssg/src/pages/home.tsx +51 -0
- package/dist/templates/ssg/src/resources/user.ts +15 -0
- package/dist/templates/ssg/src/routes.tsx +15 -0
- package/dist/templates/ssg/src/styles.css +89 -0
- package/dist/templates/ssg/src/vite-env.d.ts +5 -0
- package/dist/templates/ssg/ssg.config.ts +34 -0
- package/dist/templates/ssg/tests/app.test.tsx +19 -0
- package/dist/templates/ssg/tests/components/counter.test.tsx +18 -0
- package/dist/templates/ssg/tests/resources.test.ts +11 -0
- package/dist/templates/ssg/tests/ssg-config.test.ts +11 -0
- package/dist/templates/ssg/tsconfig.json +20 -0
- package/dist/templates/ssg/tsconfig.node.json +10 -0
- package/dist/templates/ssg/vite.config.ts +24 -0
- package/dist/templates/ssg/vitest.config.ts +17 -0
- package/dist/templates/ssr/AGENTS.md +28 -0
- package/dist/templates/ssr/README.md +38 -0
- package/dist/templates/ssr/gitignore.template +16 -0
- package/dist/templates/ssr/index.html +13 -0
- package/dist/templates/ssr/package.json +34 -0
- package/dist/templates/ssr/server.ts +16 -0
- package/dist/templates/ssr/src/app.tsx +21 -0
- package/dist/templates/ssr/src/components/counter.tsx +26 -0
- package/dist/templates/ssr/src/entry-server.tsx +10 -0
- package/dist/templates/ssr/src/main.tsx +11 -0
- package/dist/templates/ssr/src/pages/about.tsx +75 -0
- package/dist/templates/ssr/src/pages/example.tsx +113 -0
- package/dist/templates/ssr/src/pages/home.tsx +56 -0
- package/dist/templates/ssr/src/resources/user.ts +15 -0
- package/dist/templates/ssr/src/routes.tsx +13 -0
- package/dist/templates/ssr/src/styles.css +148 -0
- package/dist/templates/ssr/src/vite-server.d.ts +7 -0
- package/dist/templates/ssr/tests/app.test.tsx +24 -0
- package/dist/templates/ssr/tests/components/counter.test.tsx +13 -0
- package/dist/templates/ssr/tests/resources.test.ts +11 -0
- package/dist/templates/ssr/tsconfig.json +22 -0
- package/dist/templates/ssr/tsconfig.node.json +10 -0
- package/dist/templates/ssr/tsconfig.server.json +15 -0
- package/dist/templates/ssr/vite.config.ts +25 -0
- package/dist/templates/ssr/vitest.config.ts +13 -0
- package/dist/templates/startkit/AGENTS.md +77 -0
- package/dist/templates/startkit/README.md +192 -0
- package/dist/templates/startkit/gitignore.template +16 -0
- package/dist/templates/startkit/index.html +13 -0
- package/dist/templates/startkit/package.json +35 -0
- package/dist/templates/startkit/src/components/app-header.tsx +93 -0
- package/dist/templates/startkit/src/components/app-sidebar.tsx +95 -0
- package/dist/templates/startkit/src/components/data-table.tsx +80 -0
- package/dist/templates/startkit/src/components/empty-state.tsx +13 -0
- package/dist/templates/startkit/src/components/page-header.tsx +23 -0
- package/dist/templates/startkit/src/components/stat-card.tsx +24 -0
- package/dist/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
- package/dist/templates/startkit/src/features/accounts/account-table.tsx +79 -0
- package/dist/templates/startkit/src/lib/format.ts +31 -0
- package/dist/templates/startkit/src/lib/mock-data.ts +441 -0
- package/dist/templates/startkit/src/lib/routes.ts +116 -0
- package/dist/templates/startkit/src/main.tsx +12 -0
- package/dist/templates/startkit/src/pages/_layout.tsx +56 -0
- package/dist/templates/startkit/src/pages/auth/_layout.tsx +7 -0
- package/dist/templates/startkit/src/pages/auth/login.tsx +129 -0
- package/dist/templates/startkit/src/pages/home.tsx +83 -0
- package/dist/templates/startkit/src/pages/not-found.tsx +24 -0
- package/dist/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
- package/dist/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
- package/dist/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
- package/dist/templates/startkit/src/pages/workspace/settings.tsx +218 -0
- package/dist/templates/startkit/src/router.tsx +7 -0
- package/dist/templates/startkit/src/routes/auth-config.ts +38 -0
- package/dist/templates/startkit/src/routes/auth.ts +8 -0
- package/dist/templates/startkit/src/routes/index.ts +28 -0
- package/dist/templates/startkit/src/routes/public.ts +8 -0
- package/dist/templates/startkit/src/routes/workspace/accounts.ts +8 -0
- package/dist/templates/startkit/src/routes/workspace/index.ts +14 -0
- package/dist/templates/startkit/src/styles/components.css +396 -0
- package/dist/templates/startkit/src/styles/layout.css +192 -0
- package/dist/templates/startkit/src/styles/reset.css +38 -0
- package/dist/templates/startkit/src/styles/theme.css +76 -0
- package/dist/templates/startkit/src/styles/tokens.css +67 -0
- package/dist/templates/startkit/src/styles.css +7 -0
- package/dist/templates/startkit/src/toast.ts +55 -0
- package/dist/templates/startkit/src/utils/join-classes.ts +4 -0
- package/dist/templates/startkit/src/vite-env.d.ts +5 -0
- package/dist/templates/startkit/tests/app.test.tsx +32 -0
- package/dist/templates/startkit/tests/preferences.test.ts +43 -0
- package/dist/templates/startkit/tests/resources.test.ts +82 -0
- package/dist/templates/startkit/tsconfig.json +20 -0
- package/dist/templates/startkit/tsconfig.node.json +10 -0
- package/dist/templates/startkit/vite.config.ts +32 -0
- package/dist/templates/startkit/vitest.config.ts +13 -0
- package/dist/update-DyW1na5V.js +1140 -0
- package/dist/update-DyW1na5V.js.map +1 -0
- package/dist/update.js +3 -0
- package/package.json +84 -0
- package/skills/askr-accessibility/SKILL.md +68 -0
- package/skills/askr-accessibility/agents/openai.yaml +4 -0
- package/skills/askr-agent-execution/SKILL.md +85 -0
- package/skills/askr-agent-execution/agents/openai.yaml +4 -0
- package/skills/askr-agent-workflows/SKILL.md +57 -0
- package/skills/askr-agent-workflows/agents/openai.yaml +4 -0
- package/skills/askr-api-integration/SKILL.md +79 -0
- package/skills/askr-api-integration/agents/openai.yaml +4 -0
- package/skills/askr-app-builder/SKILL.md +99 -0
- package/skills/askr-app-builder/agents/openai.yaml +4 -0
- package/skills/askr-auth-access/SKILL.md +74 -0
- package/skills/askr-auth-access/agents/openai.yaml +4 -0
- package/skills/askr-cli-vite/SKILL.md +76 -0
- package/skills/askr-cli-vite/agents/openai.yaml +4 -0
- package/skills/askr-dashboard-charts/SKILL.md +82 -0
- package/skills/askr-dashboard-charts/agents/openai.yaml +4 -0
- package/skills/askr-design-system/SKILL.md +86 -0
- package/skills/askr-design-system/agents/openai.yaml +4 -0
- package/skills/askr-env-config/SKILL.md +74 -0
- package/skills/askr-env-config/agents/openai.yaml +4 -0
- package/skills/askr-error-loading-empty/SKILL.md +89 -0
- package/skills/askr-error-loading-empty/agents/openai.yaml +4 -0
- package/skills/askr-file-upload-artifacts/SKILL.md +77 -0
- package/skills/askr-file-upload-artifacts/agents/openai.yaml +4 -0
- package/skills/askr-forms-tables-crud/SKILL.md +98 -0
- package/skills/askr-forms-tables-crud/agents/openai.yaml +4 -0
- package/skills/askr-mental-model/SKILL.md +109 -0
- package/skills/askr-mental-model/agents/openai.yaml +4 -0
- package/skills/askr-migration-react/SKILL.md +81 -0
- package/skills/askr-migration-react/agents/openai.yaml +4 -0
- package/skills/askr-observability-debugging/SKILL.md +83 -0
- package/skills/askr-observability-debugging/agents/openai.yaml +4 -0
- package/skills/askr-project-structure/SKILL.md +79 -0
- package/skills/askr-project-structure/agents/openai.yaml +4 -0
- package/skills/askr-query-mutation/SKILL.md +115 -0
- package/skills/askr-query-mutation/agents/openai.yaml +4 -0
- package/skills/askr-realtime-streaming/SKILL.md +76 -0
- package/skills/askr-realtime-streaming/agents/openai.yaml +4 -0
- package/skills/askr-resources-data/SKILL.md +100 -0
- package/skills/askr-resources-data/agents/openai.yaml +4 -0
- package/skills/askr-routing-layouts/SKILL.md +107 -0
- package/skills/askr-routing-layouts/agents/openai.yaml +4 -0
- package/skills/askr-runtime-reactivity/SKILL.md +92 -0
- package/skills/askr-runtime-reactivity/agents/openai.yaml +4 -0
- package/skills/askr-ssr-ssg/SKILL.md +76 -0
- package/skills/askr-ssr-ssg/agents/openai.yaml +4 -0
- package/skills/askr-testing-determinism/SKILL.md +75 -0
- package/skills/askr-testing-determinism/agents/openai.yaml +4 -0
- package/skills/askr-theming/SKILL.md +86 -0
- package/skills/askr-theming/agents/openai.yaml +4 -0
- package/skills/askr-ui-composition/SKILL.md +92 -0
- package/skills/askr-ui-composition/agents/openai.yaml +4 -0
- package/templates/full-stack/AGENTS.md +12 -0
- package/templates/full-stack/README.md +18 -0
- package/templates/full-stack/gitignore.template +4 -0
- package/templates/full-stack/index.html +14 -0
- package/templates/full-stack/package.json +37 -0
- package/templates/full-stack/server.ts +13 -0
- package/templates/full-stack/src/action-authorizations.ts +10 -0
- package/templates/full-stack/src/actions/create-message.ts +10 -0
- package/templates/full-stack/src/i18n.ts +8 -0
- package/templates/full-stack/src/main.tsx +12 -0
- package/templates/full-stack/src/pages/home.tsx +25 -0
- package/templates/full-stack/src/pages/layout.tsx +33 -0
- package/templates/full-stack/src/pages/not-found.tsx +4 -0
- package/templates/full-stack/src/routes.tsx +20 -0
- package/templates/full-stack/src/schemas.ts +11 -0
- package/templates/full-stack/src/server/action-registry.ts +12 -0
- package/templates/full-stack/src/server/actions/create-message.ts +14 -0
- package/templates/full-stack/src/server/app.ts +66 -0
- package/templates/full-stack/src/server/dependencies.ts +55 -0
- package/templates/full-stack/src/server/entry-server.ts +8 -0
- package/templates/full-stack/src/telemetry.ts +4 -0
- package/templates/full-stack/src/vite-server.d.ts +6 -0
- package/templates/full-stack/tests/actions/create-message.test.ts +13 -0
- package/templates/full-stack/tsconfig.json +16 -0
- package/templates/full-stack/vite.config.ts +11 -0
- package/templates/spa/AGENTS.md +60 -0
- package/templates/spa/README.md +96 -0
- package/templates/spa/gitignore.template +16 -0
- package/templates/spa/index.html +13 -0
- package/templates/spa/package.json +35 -0
- package/templates/spa/src/adapters/operations-client.ts +90 -0
- package/templates/spa/src/components/shared/metric-card.tsx +27 -0
- package/templates/spa/src/components/shared/status-badge.tsx +24 -0
- package/templates/spa/src/features/operations/operations.query.ts +9 -0
- package/templates/spa/src/main.tsx +10 -0
- package/templates/spa/src/pages/_layout.tsx +9 -0
- package/templates/spa/src/pages/_routes.tsx +27 -0
- package/templates/spa/src/pages/app/_layout.tsx +94 -0
- package/templates/spa/src/pages/app/_routes.tsx +10 -0
- package/templates/spa/src/pages/app/admin-home.tsx +152 -0
- package/templates/spa/src/pages/app/agent-runs.tsx +93 -0
- package/templates/spa/src/pages/app/settings.tsx +91 -0
- package/templates/spa/src/pages/auth/_layout.tsx +38 -0
- package/templates/spa/src/pages/auth/_routes.tsx +6 -0
- package/templates/spa/src/pages/auth/login.tsx +63 -0
- package/templates/spa/src/pages/not-found.tsx +22 -0
- package/templates/spa/src/pages/public/_layout.tsx +47 -0
- package/templates/spa/src/pages/public/_routes.tsx +6 -0
- package/templates/spa/src/pages/public/home.tsx +143 -0
- package/templates/spa/src/shared/format.ts +12 -0
- package/templates/spa/src/shared/navigation.ts +15 -0
- package/templates/spa/src/styles/components.css +49 -0
- package/templates/spa/src/styles/layout.css +192 -0
- package/templates/spa/src/styles/reset.css +44 -0
- package/templates/spa/src/styles/theme.css +57 -0
- package/templates/spa/src/styles/tokens.css +20 -0
- package/templates/spa/src/styles.css +7 -0
- package/templates/spa/src/styles.d.ts +1 -0
- package/templates/spa/tests/app.test.tsx +37 -0
- package/templates/spa/tests/components/shared.test.tsx +12 -0
- package/templates/spa/tests/resources.test.ts +22 -0
- package/templates/spa/tsconfig.json +20 -0
- package/templates/spa/tsconfig.node.json +10 -0
- package/templates/spa/vite.config.ts +24 -0
- package/templates/spa/vitest.config.ts +17 -0
- package/templates/ssg/AGENTS.md +55 -0
- package/templates/ssg/README.md +39 -0
- package/templates/ssg/gitignore.template +17 -0
- package/templates/ssg/index.html +13 -0
- package/templates/ssg/package.json +35 -0
- package/templates/ssg/src/app.tsx +14 -0
- package/templates/ssg/src/components/badge.tsx +3 -0
- package/templates/ssg/src/components/counter.tsx +30 -0
- package/templates/ssg/src/components/site-shell.tsx +111 -0
- package/templates/ssg/src/jsx.d.ts +23 -0
- package/templates/ssg/src/main.tsx +8 -0
- package/templates/ssg/src/pages/about.tsx +82 -0
- package/templates/ssg/src/pages/content.tsx +63 -0
- package/templates/ssg/src/pages/example.tsx +97 -0
- package/templates/ssg/src/pages/home.tsx +51 -0
- package/templates/ssg/src/resources/user.ts +15 -0
- package/templates/ssg/src/routes.tsx +15 -0
- package/templates/ssg/src/styles.css +89 -0
- package/templates/ssg/src/vite-env.d.ts +5 -0
- package/templates/ssg/ssg.config.ts +34 -0
- package/templates/ssg/tests/app.test.tsx +19 -0
- package/templates/ssg/tests/components/counter.test.tsx +18 -0
- package/templates/ssg/tests/resources.test.ts +11 -0
- package/templates/ssg/tests/ssg-config.test.ts +11 -0
- package/templates/ssg/tsconfig.json +20 -0
- package/templates/ssg/tsconfig.node.json +10 -0
- package/templates/ssg/vite.config.ts +24 -0
- package/templates/ssg/vitest.config.ts +17 -0
- package/templates/ssr/AGENTS.md +28 -0
- package/templates/ssr/README.md +38 -0
- package/templates/ssr/gitignore.template +16 -0
- package/templates/ssr/index.html +13 -0
- package/templates/ssr/package.json +34 -0
- package/templates/ssr/server.ts +16 -0
- package/templates/ssr/src/app.tsx +21 -0
- package/templates/ssr/src/components/counter.tsx +26 -0
- package/templates/ssr/src/entry-server.tsx +10 -0
- package/templates/ssr/src/main.tsx +11 -0
- package/templates/ssr/src/pages/about.tsx +75 -0
- package/templates/ssr/src/pages/example.tsx +113 -0
- package/templates/ssr/src/pages/home.tsx +56 -0
- package/templates/ssr/src/resources/user.ts +15 -0
- package/templates/ssr/src/routes.tsx +13 -0
- package/templates/ssr/src/styles.css +148 -0
- package/templates/ssr/src/vite-server.d.ts +7 -0
- package/templates/ssr/tests/app.test.tsx +24 -0
- package/templates/ssr/tests/components/counter.test.tsx +13 -0
- package/templates/ssr/tests/resources.test.ts +11 -0
- package/templates/ssr/tsconfig.json +22 -0
- package/templates/ssr/tsconfig.node.json +10 -0
- package/templates/ssr/tsconfig.server.json +15 -0
- package/templates/ssr/vite.config.ts +25 -0
- package/templates/ssr/vitest.config.ts +13 -0
- package/templates/startkit/AGENTS.md +77 -0
- package/templates/startkit/README.md +192 -0
- package/templates/startkit/gitignore.template +16 -0
- package/templates/startkit/index.html +13 -0
- package/templates/startkit/package.json +35 -0
- package/templates/startkit/src/components/app-header.tsx +93 -0
- package/templates/startkit/src/components/app-sidebar.tsx +95 -0
- package/templates/startkit/src/components/data-table.tsx +80 -0
- package/templates/startkit/src/components/empty-state.tsx +13 -0
- package/templates/startkit/src/components/page-header.tsx +23 -0
- package/templates/startkit/src/components/stat-card.tsx +24 -0
- package/templates/startkit/src/features/accounts/account-filters.tsx +61 -0
- package/templates/startkit/src/features/accounts/account-table.tsx +79 -0
- package/templates/startkit/src/lib/format.ts +31 -0
- package/templates/startkit/src/lib/mock-data.ts +441 -0
- package/templates/startkit/src/lib/routes.ts +116 -0
- package/templates/startkit/src/main.tsx +12 -0
- package/templates/startkit/src/pages/_layout.tsx +56 -0
- package/templates/startkit/src/pages/auth/_layout.tsx +7 -0
- package/templates/startkit/src/pages/auth/login.tsx +129 -0
- package/templates/startkit/src/pages/home.tsx +83 -0
- package/templates/startkit/src/pages/not-found.tsx +24 -0
- package/templates/startkit/src/pages/workspace/_layout.tsx +17 -0
- package/templates/startkit/src/pages/workspace/accounts/index.tsx +217 -0
- package/templates/startkit/src/pages/workspace/dashboard.tsx +118 -0
- package/templates/startkit/src/pages/workspace/settings.tsx +218 -0
- package/templates/startkit/src/router.tsx +7 -0
- package/templates/startkit/src/routes/auth-config.ts +38 -0
- package/templates/startkit/src/routes/auth.ts +8 -0
- package/templates/startkit/src/routes/index.ts +28 -0
- package/templates/startkit/src/routes/public.ts +8 -0
- package/templates/startkit/src/routes/workspace/accounts.ts +8 -0
- package/templates/startkit/src/routes/workspace/index.ts +14 -0
- package/templates/startkit/src/styles/components.css +396 -0
- package/templates/startkit/src/styles/layout.css +192 -0
- package/templates/startkit/src/styles/reset.css +38 -0
- package/templates/startkit/src/styles/theme.css +76 -0
- package/templates/startkit/src/styles/tokens.css +67 -0
- package/templates/startkit/src/styles.css +7 -0
- package/templates/startkit/src/toast.ts +55 -0
- package/templates/startkit/src/utils/join-classes.ts +4 -0
- package/templates/startkit/src/vite-env.d.ts +5 -0
- package/templates/startkit/tests/app.test.tsx +32 -0
- package/templates/startkit/tests/preferences.test.ts +43 -0
- package/templates/startkit/tests/resources.test.ts +82 -0
- package/templates/startkit/tsconfig.json +20 -0
- package/templates/startkit/tsconfig.node.json +10 -0
- package/templates/startkit/vite.config.ts +32 -0
- package/templates/startkit/vitest.config.ts +13 -0
|
@@ -0,0 +1,1140 @@
|
|
|
1
|
+
import { t as isDirectExecution } from "./is-direct-execution-Cdlr-ZUl.js";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { parseDocument } from "yaml";
|
|
8
|
+
import { minimatch } from "minimatch";
|
|
9
|
+
import semver from "semver";
|
|
10
|
+
import { applyEdits, modify, parse } from "jsonc-parser";
|
|
11
|
+
//#region src/update/range.ts
|
|
12
|
+
const FULL_VERSION = String.raw`\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?`;
|
|
13
|
+
const PARTIAL_VERSION = String.raw`\d+(?:\.\d+){0,2}`;
|
|
14
|
+
function analyzeAtomicRange(specification) {
|
|
15
|
+
const value = specification.trim();
|
|
16
|
+
if (/^(?:\*|x|X)$/.test(value)) return {
|
|
17
|
+
shape: null,
|
|
18
|
+
tracking: true,
|
|
19
|
+
reason: "wildcard range tracks the selected tag"
|
|
20
|
+
};
|
|
21
|
+
if (new RegExp(`^${FULL_VERSION}$`).test(value) && semver.valid(value)) return {
|
|
22
|
+
shape: { kind: "exact" },
|
|
23
|
+
tracking: false,
|
|
24
|
+
reason: ""
|
|
25
|
+
};
|
|
26
|
+
const operator = value.match(new RegExp(`^([~^])\\s*(${FULL_VERSION}|${PARTIAL_VERSION})$`));
|
|
27
|
+
if (operator && semver.validRange(value)) return {
|
|
28
|
+
shape: {
|
|
29
|
+
kind: "operator",
|
|
30
|
+
operator: operator[1]
|
|
31
|
+
},
|
|
32
|
+
tracking: false,
|
|
33
|
+
reason: ""
|
|
34
|
+
};
|
|
35
|
+
const bounded = value.match(/^((?:>=|>)\s*\d+(?:\.\d+){0,2})\s+(?:<|<=)\s*\d+(?:\.\d+){0,2}$/);
|
|
36
|
+
if (bounded && semver.validRange(value)) return {
|
|
37
|
+
shape: {
|
|
38
|
+
kind: "bounded",
|
|
39
|
+
lower: bounded[1].replace(/\s+/g, "")
|
|
40
|
+
},
|
|
41
|
+
tracking: false,
|
|
42
|
+
reason: ""
|
|
43
|
+
};
|
|
44
|
+
const xRange = value.match(/^(\d+|[xX*])(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?$/);
|
|
45
|
+
if (xRange && semver.validRange(value)) {
|
|
46
|
+
const parts = xRange.slice(1).filter((part) => part !== void 0);
|
|
47
|
+
return {
|
|
48
|
+
shape: {
|
|
49
|
+
kind: "x",
|
|
50
|
+
parts,
|
|
51
|
+
wildcard: parts.find((part) => /^[xX*]$/.test(part)) ?? null
|
|
52
|
+
},
|
|
53
|
+
tracking: false,
|
|
54
|
+
reason: ""
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
shape: null,
|
|
59
|
+
tracking: false,
|
|
60
|
+
reason: "unsupported complex semver range"
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function analyzeRange(specification) {
|
|
64
|
+
const clauses = specification.split("||").map((clause) => clause.trim());
|
|
65
|
+
if (clauses.length === 1) return analyzeAtomicRange(specification);
|
|
66
|
+
if (clauses.some((clause) => clause.length === 0)) return {
|
|
67
|
+
shape: null,
|
|
68
|
+
tracking: false,
|
|
69
|
+
reason: "unsupported complex semver range"
|
|
70
|
+
};
|
|
71
|
+
const analyzed = clauses.map(analyzeAtomicRange);
|
|
72
|
+
if (analyzed.some((entry) => !entry.shape || entry.shape.kind === "union" || entry.tracking)) return {
|
|
73
|
+
shape: null,
|
|
74
|
+
tracking: false,
|
|
75
|
+
reason: "unsupported complex semver union"
|
|
76
|
+
};
|
|
77
|
+
const minimums = clauses.map((clause) => semver.minVersion(clause));
|
|
78
|
+
if (minimums.some((version) => version === null)) return {
|
|
79
|
+
shape: null,
|
|
80
|
+
tracking: false,
|
|
81
|
+
reason: "unsupported complex semver union"
|
|
82
|
+
};
|
|
83
|
+
let highestIndex = 0;
|
|
84
|
+
for (let index = 1; index < minimums.length; index += 1) if (semver.gt(minimums[index], minimums[highestIndex])) highestIndex = index;
|
|
85
|
+
return {
|
|
86
|
+
shape: {
|
|
87
|
+
kind: "union",
|
|
88
|
+
clauses: analyzed.map((entry) => entry.shape),
|
|
89
|
+
sourceClauses: clauses,
|
|
90
|
+
highestIndex
|
|
91
|
+
},
|
|
92
|
+
tracking: false,
|
|
93
|
+
reason: ""
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function isBreakingChange(allowedVersion, targetVersion) {
|
|
97
|
+
const allowed = new semver.SemVer(allowedVersion);
|
|
98
|
+
const target = new semver.SemVer(targetVersion);
|
|
99
|
+
if (allowed.major !== target.major) return true;
|
|
100
|
+
return allowed.major === 0 && allowed.minor !== target.minor;
|
|
101
|
+
}
|
|
102
|
+
function nextBreakingBoundary(version) {
|
|
103
|
+
const parsed = new semver.SemVer(version);
|
|
104
|
+
return parsed.major === 0 ? `0.${parsed.minor + 1}.0` : `${parsed.major + 1}.0.0`;
|
|
105
|
+
}
|
|
106
|
+
function rewriteXRange(shape, target) {
|
|
107
|
+
const parsed = new semver.SemVer(target);
|
|
108
|
+
const count = shape.parts.length;
|
|
109
|
+
if (shape.wildcard) {
|
|
110
|
+
const wildcardIndex = shape.parts.findIndex((part) => /^[xX*]$/.test(part));
|
|
111
|
+
if (wildcardIndex === 0) return shape.wildcard;
|
|
112
|
+
if (wildcardIndex === 1) return `${parsed.major}.${shape.wildcard}`;
|
|
113
|
+
return `${parsed.major}.${parsed.minor}.${shape.wildcard}`;
|
|
114
|
+
}
|
|
115
|
+
if (count === 1) return String(parsed.major);
|
|
116
|
+
return `${parsed.major}.${parsed.minor}`;
|
|
117
|
+
}
|
|
118
|
+
function rewriteAtomic(shape, target, forcedBreaking) {
|
|
119
|
+
if (shape.kind === "exact") return target;
|
|
120
|
+
if (shape.kind === "operator") return `${shape.operator}${target}`;
|
|
121
|
+
if (shape.kind === "x") return rewriteXRange(shape, target);
|
|
122
|
+
const boundary = nextBreakingBoundary(target);
|
|
123
|
+
return forcedBreaking ? `>=${target} <${boundary}` : `${shape.lower} <${boundary}`;
|
|
124
|
+
}
|
|
125
|
+
function rewriteRange(shape, target, forcedBreaking) {
|
|
126
|
+
if (shape.kind !== "union") return rewriteAtomic(shape, target, forcedBreaking);
|
|
127
|
+
const highestShape = shape.clauses[shape.highestIndex];
|
|
128
|
+
if (forcedBreaking) return rewriteAtomic(highestShape, target, true);
|
|
129
|
+
const rewritten = [...shape.sourceClauses];
|
|
130
|
+
rewritten[shape.highestIndex] = rewriteAtomic(highestShape, target, false);
|
|
131
|
+
return rewritten.join(" || ");
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/update/npm-adapters.ts
|
|
135
|
+
const require = createRequire(import.meta.url);
|
|
136
|
+
const npmPackageArg = require("npm-package-arg");
|
|
137
|
+
const mapDeclaredWorkspaces = require("@npmcli/map-workspaces");
|
|
138
|
+
const npmRegistryFetch = require("npm-registry-fetch");
|
|
139
|
+
const NpmConfig = require("@npmcli/config");
|
|
140
|
+
const npmConfigDefinitions = require("@npmcli/config/lib/definitions");
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/update/types.ts
|
|
143
|
+
const DEPENDENCY_SECTIONS = [
|
|
144
|
+
"dependencies",
|
|
145
|
+
"devDependencies",
|
|
146
|
+
"optionalDependencies",
|
|
147
|
+
"peerDependencies"
|
|
148
|
+
];
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/update/discovery.ts
|
|
151
|
+
async function isFile(filePath) {
|
|
152
|
+
return (await fs.stat(filePath).catch(() => null))?.isFile() ?? false;
|
|
153
|
+
}
|
|
154
|
+
async function readManifest(manifestPath) {
|
|
155
|
+
let source;
|
|
156
|
+
try {
|
|
157
|
+
source = await fs.readFile(manifestPath, "utf8");
|
|
158
|
+
} catch {
|
|
159
|
+
throw new Error(`Unable to read manifest: ${manifestPath}`);
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const value = JSON.parse(source.replace(/^\uFEFF/, ""));
|
|
163
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error();
|
|
164
|
+
return value;
|
|
165
|
+
} catch {
|
|
166
|
+
throw new Error(`Malformed package manifest: ${manifestPath}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function packageWorkspacePatterns(manifest) {
|
|
170
|
+
if (!("workspaces" in manifest)) return null;
|
|
171
|
+
const declaration = manifest.workspaces;
|
|
172
|
+
const patterns = Array.isArray(declaration) ? declaration : declaration && typeof declaration === "object" && !Array.isArray(declaration) ? declaration.packages : null;
|
|
173
|
+
if (!Array.isArray(patterns) || patterns.some((pattern) => typeof pattern !== "string")) throw new Error("Invalid package.json workspaces declaration; expected an array of paths.");
|
|
174
|
+
return patterns;
|
|
175
|
+
}
|
|
176
|
+
async function pnpmWorkspacePatterns(root) {
|
|
177
|
+
const workspacePath = path.join(root, "pnpm-workspace.yaml");
|
|
178
|
+
if (!await isFile(workspacePath)) return null;
|
|
179
|
+
const document = parseDocument(await fs.readFile(workspacePath, "utf8"), { prettyErrors: false });
|
|
180
|
+
if (document.errors.length > 0) throw new Error(`Malformed pnpm workspace declaration: ${workspacePath}`);
|
|
181
|
+
const value = document.toJS();
|
|
182
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid pnpm workspace declaration; expected a mapping with packages.");
|
|
183
|
+
const packages = value.packages;
|
|
184
|
+
if (!Array.isArray(packages) || packages.some((pattern) => typeof pattern !== "string")) throw new Error("Invalid pnpm workspace declaration; expected packages to be an array.");
|
|
185
|
+
return packages;
|
|
186
|
+
}
|
|
187
|
+
async function findProjectRoot(start) {
|
|
188
|
+
const resolved = path.resolve(start);
|
|
189
|
+
if (!(await fs.stat(resolved).catch(() => null))?.isDirectory()) throw new Error(`Working directory does not exist: ${resolved}`);
|
|
190
|
+
let directory = resolved;
|
|
191
|
+
let nearestManifestDirectory = null;
|
|
192
|
+
while (true) {
|
|
193
|
+
const manifestPath = path.join(directory, "package.json");
|
|
194
|
+
const hasManifest = await isFile(manifestPath);
|
|
195
|
+
if (hasManifest) {
|
|
196
|
+
const manifest = await readManifest(manifestPath);
|
|
197
|
+
nearestManifestDirectory ??= directory;
|
|
198
|
+
if (packageWorkspacePatterns(manifest) !== null) return directory;
|
|
199
|
+
}
|
|
200
|
+
if (await isFile(path.join(directory, "pnpm-workspace.yaml"))) {
|
|
201
|
+
if (!hasManifest) throw new Error(`Workspace root is missing package.json: ${directory}`);
|
|
202
|
+
await pnpmWorkspacePatterns(directory);
|
|
203
|
+
return directory;
|
|
204
|
+
}
|
|
205
|
+
const parent = path.dirname(directory);
|
|
206
|
+
if (parent === directory) break;
|
|
207
|
+
directory = parent;
|
|
208
|
+
}
|
|
209
|
+
if (nearestManifestDirectory) return nearestManifestDirectory;
|
|
210
|
+
throw new Error(`No package.json found from ${resolved}.`);
|
|
211
|
+
}
|
|
212
|
+
function parsePolicy(manifest) {
|
|
213
|
+
const empty = {
|
|
214
|
+
ignore: [],
|
|
215
|
+
tags: {}
|
|
216
|
+
};
|
|
217
|
+
if (!("askr" in manifest)) return empty;
|
|
218
|
+
if (!manifest.askr || typeof manifest.askr !== "object" || Array.isArray(manifest.askr)) throw new Error("Invalid askr update configuration in the workspace root.");
|
|
219
|
+
const update = manifest.askr.update;
|
|
220
|
+
if (update === void 0) return empty;
|
|
221
|
+
if (!update || typeof update !== "object" || Array.isArray(update)) throw new Error("Invalid askr.update configuration in the workspace root.");
|
|
222
|
+
const config = update;
|
|
223
|
+
const ignore = config.ignore ?? [];
|
|
224
|
+
const tags = config.tags ?? {};
|
|
225
|
+
if (!Array.isArray(ignore) || ignore.some((entry) => typeof entry !== "string")) throw new Error("Invalid askr.update.ignore configuration; expected an array of patterns.");
|
|
226
|
+
if (!tags || typeof tags !== "object" || Array.isArray(tags) || Object.entries(tags).some(([name, tag]) => !name || typeof tag !== "string" || !tag)) throw new Error("Invalid askr.update.tags configuration; expected package-to-tag strings.");
|
|
227
|
+
return {
|
|
228
|
+
ignore,
|
|
229
|
+
tags
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function relativeManifestPath(root, manifestPath) {
|
|
233
|
+
return path.relative(root, manifestPath).split(path.sep).join("/") || "package.json";
|
|
234
|
+
}
|
|
235
|
+
function workspaceName(manifest, fallback) {
|
|
236
|
+
return typeof manifest.name === "string" && manifest.name.trim() ? manifest.name : fallback;
|
|
237
|
+
}
|
|
238
|
+
async function discoverWorkspaces(root) {
|
|
239
|
+
const rootManifestPath = path.join(root, "package.json");
|
|
240
|
+
const rootManifest = await readManifest(rootManifestPath);
|
|
241
|
+
const policy = parsePolicy(rootManifest);
|
|
242
|
+
const packagePatterns = packageWorkspacePatterns(rootManifest) ?? [];
|
|
243
|
+
const pnpmPatterns = await pnpmWorkspacePatterns(root) ?? [];
|
|
244
|
+
const patterns = [...packagePatterns, ...pnpmPatterns];
|
|
245
|
+
const mapped = patterns.length > 0 ? await mapDeclaredWorkspaces({
|
|
246
|
+
cwd: root,
|
|
247
|
+
pkg: { workspaces: patterns }
|
|
248
|
+
}) : /* @__PURE__ */ new Map();
|
|
249
|
+
const rootName = workspaceName(rootManifest, "(root)");
|
|
250
|
+
if (mapped.has(rootName)) throw new Error(`Duplicate workspace name '${rootName}' includes the workspace root.`);
|
|
251
|
+
const workspaces = [{
|
|
252
|
+
name: rootName,
|
|
253
|
+
directory: root,
|
|
254
|
+
manifestPath: rootManifestPath,
|
|
255
|
+
relativeManifestPath: "package.json",
|
|
256
|
+
manifest: rootManifest,
|
|
257
|
+
isRoot: true
|
|
258
|
+
}];
|
|
259
|
+
for (const [mappedName, directory] of mapped) {
|
|
260
|
+
const manifestPath = path.join(directory, "package.json");
|
|
261
|
+
const manifest = await readManifest(manifestPath);
|
|
262
|
+
workspaces.push({
|
|
263
|
+
name: workspaceName(manifest, mappedName),
|
|
264
|
+
directory,
|
|
265
|
+
manifestPath,
|
|
266
|
+
relativeManifestPath: relativeManifestPath(root, manifestPath),
|
|
267
|
+
manifest,
|
|
268
|
+
isRoot: false
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
workspaces.sort((left, right) => {
|
|
272
|
+
if (left.isRoot !== right.isRoot) return left.isRoot ? -1 : 1;
|
|
273
|
+
return left.name.localeCompare(right.name) || left.manifestPath.localeCompare(right.manifestPath);
|
|
274
|
+
});
|
|
275
|
+
return {
|
|
276
|
+
policy,
|
|
277
|
+
rootManifest,
|
|
278
|
+
workspaces
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function matchesAny(value, patterns) {
|
|
282
|
+
return patterns.some((pattern) => minimatch(value, pattern, { dot: true }));
|
|
283
|
+
}
|
|
284
|
+
function classifySpecification(packageName, specification, directory, localNames) {
|
|
285
|
+
if (localNames.has(packageName)) return {
|
|
286
|
+
kind: "local",
|
|
287
|
+
registryManaged: false,
|
|
288
|
+
reason: "dependency resolves to a discovered workspace"
|
|
289
|
+
};
|
|
290
|
+
if (/^workspace:/i.test(specification)) return {
|
|
291
|
+
kind: "local",
|
|
292
|
+
registryManaged: false,
|
|
293
|
+
reason: "workspace protocol is not registry-managed"
|
|
294
|
+
};
|
|
295
|
+
if (/^link:/i.test(specification)) return {
|
|
296
|
+
kind: "local",
|
|
297
|
+
registryManaged: false,
|
|
298
|
+
reason: "link protocol is not registry-managed"
|
|
299
|
+
};
|
|
300
|
+
let parsed;
|
|
301
|
+
try {
|
|
302
|
+
parsed = npmPackageArg.resolve(packageName, specification, directory);
|
|
303
|
+
} catch {
|
|
304
|
+
return {
|
|
305
|
+
kind: "manual",
|
|
306
|
+
registryManaged: false,
|
|
307
|
+
reason: "unsupported dependency specification"
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
if ([
|
|
311
|
+
"directory",
|
|
312
|
+
"file",
|
|
313
|
+
"git",
|
|
314
|
+
"remote"
|
|
315
|
+
].includes(parsed.type)) return {
|
|
316
|
+
kind: "local",
|
|
317
|
+
registryManaged: false,
|
|
318
|
+
reason: `${parsed.type} specification is not registry-managed`
|
|
319
|
+
};
|
|
320
|
+
if (parsed.type === "alias") return {
|
|
321
|
+
kind: "manual",
|
|
322
|
+
registryManaged: false,
|
|
323
|
+
reason: "npm aliases require manual review"
|
|
324
|
+
};
|
|
325
|
+
if (parsed.type === "tag") return {
|
|
326
|
+
kind: "current",
|
|
327
|
+
registryManaged: true,
|
|
328
|
+
reason: "tracking tag is not rewritten"
|
|
329
|
+
};
|
|
330
|
+
if (parsed.type !== "range" && parsed.type !== "version") return {
|
|
331
|
+
kind: "manual",
|
|
332
|
+
registryManaged: false,
|
|
333
|
+
reason: "unsupported dependency specification"
|
|
334
|
+
};
|
|
335
|
+
const analysis = analyzeRange(specification);
|
|
336
|
+
if (analysis.tracking) return {
|
|
337
|
+
kind: "current",
|
|
338
|
+
registryManaged: true,
|
|
339
|
+
reason: analysis.reason
|
|
340
|
+
};
|
|
341
|
+
if (!analysis.shape) return {
|
|
342
|
+
kind: "manual",
|
|
343
|
+
registryManaged: false,
|
|
344
|
+
reason: analysis.reason
|
|
345
|
+
};
|
|
346
|
+
return {
|
|
347
|
+
kind: "fetch",
|
|
348
|
+
registryManaged: true,
|
|
349
|
+
reason: ""
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function collectOccurrences(root, workspaces, localNames, policy, packagePatterns) {
|
|
353
|
+
const occurrences = [];
|
|
354
|
+
for (const workspace of workspaces) for (const section of DEPENDENCY_SECTIONS) {
|
|
355
|
+
const dependencies = workspace.manifest[section];
|
|
356
|
+
if (dependencies === void 0) continue;
|
|
357
|
+
if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) throw new Error(`Invalid ${section} in ${workspace.relativeManifestPath}; expected an object.`);
|
|
358
|
+
for (const [packageName, specification] of Object.entries(dependencies)) {
|
|
359
|
+
if (typeof specification !== "string") throw new Error(`Invalid ${section}.${packageName} in ${workspace.relativeManifestPath}.`);
|
|
360
|
+
if (packagePatterns.length > 0 && !matchesAny(packageName, packagePatterns)) continue;
|
|
361
|
+
if (packagePatterns.length === 0 && matchesAny(packageName, policy.ignore)) continue;
|
|
362
|
+
occurrences.push({
|
|
363
|
+
package: packageName,
|
|
364
|
+
workspace: workspace.name,
|
|
365
|
+
manifestPath: workspace.manifestPath,
|
|
366
|
+
relativeManifestPath: relativeManifestPath(root, workspace.manifestPath),
|
|
367
|
+
section,
|
|
368
|
+
currentSpecification: specification,
|
|
369
|
+
...classifySpecification(packageName, specification, workspace.directory, localNames)
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
const sectionOrder = new Map(DEPENDENCY_SECTIONS.map((section, index) => [section, index]));
|
|
374
|
+
occurrences.sort((left, right) => left.package.localeCompare(right.package) || left.workspace.localeCompare(right.workspace) || left.relativeManifestPath.localeCompare(right.relativeManifestPath) || sectionOrder.get(left.section) - sectionOrder.get(right.section));
|
|
375
|
+
return occurrences;
|
|
376
|
+
}
|
|
377
|
+
async function discoverProject(options) {
|
|
378
|
+
const root = await findProjectRoot(options.cwd);
|
|
379
|
+
const { policy, workspaces } = await discoverWorkspaces(root);
|
|
380
|
+
const selectedWorkspaces = options.workspacePatterns.length === 0 ? workspaces : workspaces.filter((workspace) => matchesAny(workspace.name, options.workspacePatterns));
|
|
381
|
+
if (selectedWorkspaces.length === 0) throw new Error("No discovered workspace matches the requested --workspace filters.");
|
|
382
|
+
const localNames = new Set(workspaces.map((workspace) => workspace.name));
|
|
383
|
+
return {
|
|
384
|
+
root,
|
|
385
|
+
workspaces,
|
|
386
|
+
selectedWorkspaces,
|
|
387
|
+
policy,
|
|
388
|
+
occurrences: collectOccurrences(root, selectedWorkspaces, localNames, policy, options.packagePatterns),
|
|
389
|
+
contextOccurrences: collectOccurrences(root, selectedWorkspaces, localNames, {
|
|
390
|
+
ignore: [],
|
|
391
|
+
tags: policy.tags
|
|
392
|
+
}, [])
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
//#endregion
|
|
396
|
+
//#region src/update/planner.ts
|
|
397
|
+
const STATUS_PRIORITY = {
|
|
398
|
+
current: 0,
|
|
399
|
+
local: 1,
|
|
400
|
+
safe: 2,
|
|
401
|
+
breaking: 3,
|
|
402
|
+
manual: 4,
|
|
403
|
+
error: 5
|
|
404
|
+
};
|
|
405
|
+
function publishedVersions(packument) {
|
|
406
|
+
return Object.keys(packument.versions ?? {}).filter((version) => semver.valid(version) !== null).sort(semver.compare);
|
|
407
|
+
}
|
|
408
|
+
function selectedTarget(packument, tag) {
|
|
409
|
+
const value = packument["dist-tags"]?.[tag];
|
|
410
|
+
return typeof value === "string" && semver.valid(value) ? value : null;
|
|
411
|
+
}
|
|
412
|
+
function plannedOccurrence(occurrence, packument, failure, selectedTag, force) {
|
|
413
|
+
const base = {
|
|
414
|
+
workspace: occurrence.workspace,
|
|
415
|
+
manifestPath: occurrence.manifestPath,
|
|
416
|
+
relativeManifestPath: occurrence.relativeManifestPath,
|
|
417
|
+
section: occurrence.section,
|
|
418
|
+
currentSpecification: occurrence.currentSpecification,
|
|
419
|
+
proposedSpecification: null,
|
|
420
|
+
allowedVersion: null
|
|
421
|
+
};
|
|
422
|
+
if (occurrence.kind === "local") return {
|
|
423
|
+
targetVersion: null,
|
|
424
|
+
occurrence: {
|
|
425
|
+
...base,
|
|
426
|
+
status: "local",
|
|
427
|
+
reason: occurrence.reason
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
if (occurrence.kind === "manual") return {
|
|
431
|
+
targetVersion: null,
|
|
432
|
+
occurrence: {
|
|
433
|
+
...base,
|
|
434
|
+
status: "manual",
|
|
435
|
+
reason: occurrence.reason
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
if (failure) return {
|
|
439
|
+
targetVersion: null,
|
|
440
|
+
occurrence: {
|
|
441
|
+
...base,
|
|
442
|
+
status: "error",
|
|
443
|
+
reason: failure
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
if (occurrence.kind === "current") return {
|
|
447
|
+
targetVersion: packument ? selectedTarget(packument, selectedTag) : null,
|
|
448
|
+
occurrence: {
|
|
449
|
+
...base,
|
|
450
|
+
status: "current",
|
|
451
|
+
reason: occurrence.reason
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
if (!packument) return {
|
|
455
|
+
targetVersion: null,
|
|
456
|
+
occurrence: {
|
|
457
|
+
...base,
|
|
458
|
+
status: "error",
|
|
459
|
+
reason: "package metadata is unavailable"
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
const targetVersion = selectedTarget(packument, selectedTag);
|
|
463
|
+
if (!targetVersion) return {
|
|
464
|
+
targetVersion: null,
|
|
465
|
+
occurrence: {
|
|
466
|
+
...base,
|
|
467
|
+
status: "error",
|
|
468
|
+
reason: `dist-tag '${selectedTag}' is not published`
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
const versions = publishedVersions(packument);
|
|
472
|
+
if (!versions.includes(targetVersion)) return {
|
|
473
|
+
targetVersion: null,
|
|
474
|
+
occurrence: {
|
|
475
|
+
...base,
|
|
476
|
+
status: "error",
|
|
477
|
+
reason: `dist-tag '${selectedTag}' does not identify a published version`
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
const allowedVersion = semver.maxSatisfying(versions, occurrence.currentSpecification);
|
|
481
|
+
if (!allowedVersion) return {
|
|
482
|
+
targetVersion,
|
|
483
|
+
occurrence: {
|
|
484
|
+
...base,
|
|
485
|
+
status: "manual",
|
|
486
|
+
reason: "no published version satisfies the current specification"
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
if (semver.satisfies(targetVersion, occurrence.currentSpecification) || !semver.gt(targetVersion, allowedVersion)) return {
|
|
490
|
+
targetVersion,
|
|
491
|
+
occurrence: {
|
|
492
|
+
...base,
|
|
493
|
+
allowedVersion,
|
|
494
|
+
status: "current",
|
|
495
|
+
reason: "selected target is already covered by the current specification"
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
const analysis = analyzeRange(occurrence.currentSpecification);
|
|
499
|
+
if (!analysis.shape) return {
|
|
500
|
+
targetVersion,
|
|
501
|
+
occurrence: {
|
|
502
|
+
...base,
|
|
503
|
+
allowedVersion,
|
|
504
|
+
status: "manual",
|
|
505
|
+
reason: analysis.reason
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
const breaking = isBreakingChange(allowedVersion, targetVersion);
|
|
509
|
+
const eligible = !breaking || force;
|
|
510
|
+
return {
|
|
511
|
+
targetVersion,
|
|
512
|
+
occurrence: {
|
|
513
|
+
...base,
|
|
514
|
+
allowedVersion,
|
|
515
|
+
proposedSpecification: eligible ? rewriteRange(analysis.shape, targetVersion, breaking) : null,
|
|
516
|
+
status: breaking ? "breaking" : "safe",
|
|
517
|
+
reason: breaking ? eligible ? "breaking update included by --force" : "breaking update requires --upgrade --force" : "compatible update is available"
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function occurrenceKey(occurrence, packageName) {
|
|
522
|
+
return [
|
|
523
|
+
occurrence.manifestPath,
|
|
524
|
+
occurrence.section,
|
|
525
|
+
packageName ?? occurrence.package,
|
|
526
|
+
occurrence.currentSpecification
|
|
527
|
+
].join("\0");
|
|
528
|
+
}
|
|
529
|
+
function resolveSpecificationVersion(specification, packument) {
|
|
530
|
+
const versions = publishedVersions(packument);
|
|
531
|
+
let parsed;
|
|
532
|
+
try {
|
|
533
|
+
parsed = npmPackageArg.resolve("placeholder", specification);
|
|
534
|
+
} catch {
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
if (parsed.type === "tag") {
|
|
538
|
+
const tagged = packument["dist-tags"]?.[parsed.rawSpec];
|
|
539
|
+
return typeof tagged === "string" && semver.valid(tagged) ? tagged : null;
|
|
540
|
+
}
|
|
541
|
+
if (parsed.type === "version") return semver.valid(parsed.rawSpec);
|
|
542
|
+
if (parsed.type === "range") return semver.maxSatisfying(versions, parsed.rawSpec);
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
function versionMetadata(packument, version) {
|
|
546
|
+
const metadata = packument.versions?.[version];
|
|
547
|
+
return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : null;
|
|
548
|
+
}
|
|
549
|
+
function applyPeerCompatibilityGuard(decisions, contextOccurrences, packuments) {
|
|
550
|
+
const plannedByKey = /* @__PURE__ */ new Map();
|
|
551
|
+
for (const decision of decisions) for (const occurrence of decision.occurrences) plannedByKey.set(occurrenceKey(occurrence, decision.package), occurrence);
|
|
552
|
+
const contextByWorkspace = /* @__PURE__ */ new Map();
|
|
553
|
+
for (const occurrence of contextOccurrences) {
|
|
554
|
+
const entries = contextByWorkspace.get(occurrence.workspace) ?? [];
|
|
555
|
+
entries.push(occurrence);
|
|
556
|
+
contextByWorkspace.set(occurrence.workspace, entries);
|
|
557
|
+
}
|
|
558
|
+
for (const [workspace, context] of contextByWorkspace) {
|
|
559
|
+
const states = context.flatMap((dependency) => {
|
|
560
|
+
if (!dependency.registryManaged) return [];
|
|
561
|
+
const packument = packuments.get(dependency.package);
|
|
562
|
+
if (!packument) return [];
|
|
563
|
+
const planned = plannedByKey.get(occurrenceKey(dependency));
|
|
564
|
+
const currentVersion = resolveSpecificationVersion(dependency.currentSpecification, packument);
|
|
565
|
+
const futureVersion = resolveSpecificationVersion(planned?.proposedSpecification ?? dependency.currentSpecification, packument);
|
|
566
|
+
return currentVersion && futureVersion ? [{
|
|
567
|
+
dependency,
|
|
568
|
+
packument,
|
|
569
|
+
planned,
|
|
570
|
+
currentVersion,
|
|
571
|
+
futureVersion,
|
|
572
|
+
changed: Boolean(planned?.proposedSpecification)
|
|
573
|
+
}] : [];
|
|
574
|
+
});
|
|
575
|
+
const blockers = /* @__PURE__ */ new Map();
|
|
576
|
+
for (const provider of states) {
|
|
577
|
+
const currentPeers = versionMetadata(provider.packument, provider.currentVersion)?.peerDependencies ?? {};
|
|
578
|
+
const futurePeers = versionMetadata(provider.packument, provider.futureVersion)?.peerDependencies ?? {};
|
|
579
|
+
const peerNames = /* @__PURE__ */ new Set([...Object.keys(currentPeers), ...Object.keys(futurePeers)]);
|
|
580
|
+
for (const peerName of peerNames) {
|
|
581
|
+
const currentRequirement = currentPeers[peerName];
|
|
582
|
+
const futureRequirement = futurePeers[peerName];
|
|
583
|
+
if (futureRequirement !== void 0 && typeof futureRequirement !== "string") continue;
|
|
584
|
+
for (const peer of states.filter((state) => state.dependency.package === peerName)) {
|
|
585
|
+
const currentAccepted = typeof currentRequirement !== "string" || semver.satisfies(peer.currentVersion, currentRequirement);
|
|
586
|
+
const futureAccepted = typeof futureRequirement !== "string" || semver.satisfies(peer.futureVersion, futureRequirement);
|
|
587
|
+
if (!currentAccepted || futureAccepted) continue;
|
|
588
|
+
const reason = `${provider.dependency.package}@${provider.futureVersion} requires ${peerName}@${futureRequirement}`;
|
|
589
|
+
if (provider.changed && provider.planned) blockers.set(provider.planned, reason);
|
|
590
|
+
if (peer.changed && peer.planned) blockers.set(peer.planned, reason);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
for (const [planned, reason] of blockers) {
|
|
595
|
+
planned.status = "manual";
|
|
596
|
+
planned.proposedSpecification = null;
|
|
597
|
+
planned.reason = reason;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
function aggregateStatus(occurrences) {
|
|
602
|
+
return occurrences.reduce((status, occurrence) => STATUS_PRIORITY[occurrence.status] > STATUS_PRIORITY[status] ? occurrence.status : status, "current");
|
|
603
|
+
}
|
|
604
|
+
function summarize(decisions) {
|
|
605
|
+
const summary = {
|
|
606
|
+
packages: decisions.length,
|
|
607
|
+
occurrences: 0,
|
|
608
|
+
changedOccurrences: 0,
|
|
609
|
+
current: 0,
|
|
610
|
+
safe: 0,
|
|
611
|
+
breaking: 0,
|
|
612
|
+
local: 0,
|
|
613
|
+
manual: 0,
|
|
614
|
+
error: 0
|
|
615
|
+
};
|
|
616
|
+
for (const decision of decisions) {
|
|
617
|
+
decision.status = aggregateStatus(decision.occurrences);
|
|
618
|
+
decision.reason = decision.occurrences.find((entry) => entry.status === decision.status)?.reason ?? "";
|
|
619
|
+
summary[decision.status] += 1;
|
|
620
|
+
summary.occurrences += decision.occurrences.length;
|
|
621
|
+
summary.changedOccurrences += decision.occurrences.filter((entry) => entry.proposedSpecification).length;
|
|
622
|
+
}
|
|
623
|
+
return summary;
|
|
624
|
+
}
|
|
625
|
+
function planUpdates(options) {
|
|
626
|
+
const failures = options.failures ?? /* @__PURE__ */ new Map();
|
|
627
|
+
const tags = options.tags ?? {};
|
|
628
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
629
|
+
for (const occurrence of options.occurrences) {
|
|
630
|
+
const entries = grouped.get(occurrence.package) ?? [];
|
|
631
|
+
entries.push(occurrence);
|
|
632
|
+
grouped.set(occurrence.package, entries);
|
|
633
|
+
}
|
|
634
|
+
const decisions = [...grouped.entries()].sort(([left], [right]) => left.localeCompare(right)).map(([packageName, occurrences]) => {
|
|
635
|
+
const selectedTag = options.cliTag ?? tags[packageName] ?? "latest";
|
|
636
|
+
const planned = occurrences.map((occurrence) => plannedOccurrence(occurrence, options.packuments.get(packageName), failures.get(packageName), selectedTag, options.force ?? false));
|
|
637
|
+
const targetVersion = planned.find((entry) => entry.targetVersion)?.targetVersion ?? null;
|
|
638
|
+
const plannedOccurrences = planned.map((entry) => entry.occurrence);
|
|
639
|
+
const status = aggregateStatus(plannedOccurrences);
|
|
640
|
+
return {
|
|
641
|
+
package: packageName,
|
|
642
|
+
selectedTag,
|
|
643
|
+
targetVersion,
|
|
644
|
+
status,
|
|
645
|
+
reason: plannedOccurrences.find((entry) => entry.status === status)?.reason ?? "",
|
|
646
|
+
occurrences: plannedOccurrences
|
|
647
|
+
};
|
|
648
|
+
});
|
|
649
|
+
const selectedNames = new Set(grouped.keys());
|
|
650
|
+
for (const [packageName, failure] of [...failures].sort(([left], [right]) => left.localeCompare(right))) {
|
|
651
|
+
if (selectedNames.has(packageName)) continue;
|
|
652
|
+
const context = (options.contextOccurrences ?? []).filter((occurrence) => occurrence.package === packageName).map((occurrence) => ({
|
|
653
|
+
workspace: occurrence.workspace,
|
|
654
|
+
manifestPath: occurrence.manifestPath,
|
|
655
|
+
relativeManifestPath: occurrence.relativeManifestPath,
|
|
656
|
+
section: occurrence.section,
|
|
657
|
+
currentSpecification: occurrence.currentSpecification,
|
|
658
|
+
proposedSpecification: null,
|
|
659
|
+
allowedVersion: null,
|
|
660
|
+
status: "error",
|
|
661
|
+
reason: `peer compatibility lookup failed: ${failure}`
|
|
662
|
+
}));
|
|
663
|
+
decisions.push({
|
|
664
|
+
package: packageName,
|
|
665
|
+
selectedTag: options.cliTag ?? tags[packageName] ?? "latest",
|
|
666
|
+
targetVersion: null,
|
|
667
|
+
status: "error",
|
|
668
|
+
reason: `peer compatibility lookup failed: ${failure}`,
|
|
669
|
+
occurrences: context
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
decisions.sort((left, right) => left.package.localeCompare(right.package));
|
|
673
|
+
applyPeerCompatibilityGuard(decisions, options.contextOccurrences ?? options.occurrences, options.packuments);
|
|
674
|
+
const summary = summarize(decisions);
|
|
675
|
+
return {
|
|
676
|
+
decisions,
|
|
677
|
+
summary,
|
|
678
|
+
hasErrors: summary.error > 0
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
//#endregion
|
|
682
|
+
//#region src/update/registry.ts
|
|
683
|
+
const ABBREVIATED_PACKUMENT = "application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*";
|
|
684
|
+
function npmPathFromExecutable(executable) {
|
|
685
|
+
let directory = path.dirname(path.resolve(executable));
|
|
686
|
+
for (let depth = 0; depth < 5; depth += 1) {
|
|
687
|
+
const manifestPath = path.join(directory, "package.json");
|
|
688
|
+
if (existsSync(manifestPath)) try {
|
|
689
|
+
if (createRequire(import.meta.url)(manifestPath).name === "npm") return directory;
|
|
690
|
+
} catch {}
|
|
691
|
+
const parent = path.dirname(directory);
|
|
692
|
+
if (parent === directory) break;
|
|
693
|
+
directory = parent;
|
|
694
|
+
}
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
function resolveNpmPath(env) {
|
|
698
|
+
if (env.npm_execpath) {
|
|
699
|
+
const fromEnvironment = npmPathFromExecutable(env.npm_execpath);
|
|
700
|
+
if (fromEnvironment) return fromEnvironment;
|
|
701
|
+
}
|
|
702
|
+
const executableDirectory = path.dirname(process.execPath);
|
|
703
|
+
const installed = (process.platform === "win32" ? [path.join(executableDirectory, "node_modules", "npm")] : [path.resolve(executableDirectory, "..", "lib", "node_modules", "npm")]).find((candidate) => existsSync(path.join(candidate, "package.json")));
|
|
704
|
+
if (installed) return installed;
|
|
705
|
+
return path.dirname(createRequire(import.meta.url).resolve("@npmcli/config/package.json"));
|
|
706
|
+
}
|
|
707
|
+
async function loadNpmConfiguration(root, env = process.env) {
|
|
708
|
+
try {
|
|
709
|
+
const config = new NpmConfig({
|
|
710
|
+
argv: [],
|
|
711
|
+
cwd: root,
|
|
712
|
+
definitions: npmConfigDefinitions.definitions,
|
|
713
|
+
env,
|
|
714
|
+
flatten: npmConfigDefinitions.flatten,
|
|
715
|
+
npmPath: resolveNpmPath(env),
|
|
716
|
+
shorthands: npmConfigDefinitions.shorthands
|
|
717
|
+
});
|
|
718
|
+
await config.load();
|
|
719
|
+
if (!config.validate()) throw new Error("Invalid npm configuration");
|
|
720
|
+
return { ...config.flat };
|
|
721
|
+
} catch {
|
|
722
|
+
throw new Error("Unable to load or validate npm configuration.");
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
function sanitizeRegistryError(error) {
|
|
726
|
+
const value = error && typeof error === "object" ? error : {};
|
|
727
|
+
if (value.statusCode === 404) return "package was not found in the selected registry";
|
|
728
|
+
if (value.statusCode === 401 || value.statusCode === 403) return "registry authentication or authorization failed";
|
|
729
|
+
const code = typeof value.code === "string" ? value.code.toUpperCase() : "";
|
|
730
|
+
if ([
|
|
731
|
+
"ETIMEDOUT",
|
|
732
|
+
"ETIMEOUT",
|
|
733
|
+
"FETCH_ERROR",
|
|
734
|
+
"ECONNRESET"
|
|
735
|
+
].includes(code)) return "registry request timed out or was interrupted";
|
|
736
|
+
if (/^[A-Z][A-Z0-9_]{1,30}$/.test(code)) return `registry request failed (${code})`;
|
|
737
|
+
return "registry request failed";
|
|
738
|
+
}
|
|
739
|
+
function isRecord(value) {
|
|
740
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
741
|
+
}
|
|
742
|
+
function isPackument(value) {
|
|
743
|
+
return isRecord(value) && isRecord(value["dist-tags"]) && isRecord(value.versions);
|
|
744
|
+
}
|
|
745
|
+
async function fetchPackuments(packageNames, configuration, fetchJson = npmRegistryFetch.json.bind(npmRegistryFetch)) {
|
|
746
|
+
const names = [...new Set(packageNames)].sort((left, right) => left.localeCompare(right));
|
|
747
|
+
const packuments = /* @__PURE__ */ new Map();
|
|
748
|
+
const failures = /* @__PURE__ */ new Map();
|
|
749
|
+
let nextIndex = 0;
|
|
750
|
+
const worker = async () => {
|
|
751
|
+
while (nextIndex < names.length) {
|
|
752
|
+
const packageName = names[nextIndex];
|
|
753
|
+
nextIndex += 1;
|
|
754
|
+
const spec = npmPackageArg(packageName);
|
|
755
|
+
try {
|
|
756
|
+
const result = await fetchJson(`/${spec.escapedName}`, {
|
|
757
|
+
...configuration,
|
|
758
|
+
headers: {
|
|
759
|
+
...configuration.headers,
|
|
760
|
+
accept: ABBREVIATED_PACKUMENT
|
|
761
|
+
},
|
|
762
|
+
offline: false,
|
|
763
|
+
preferOffline: false,
|
|
764
|
+
preferOnline: true,
|
|
765
|
+
spec
|
|
766
|
+
});
|
|
767
|
+
if (!isPackument(result)) failures.set(packageName, "registry returned malformed package metadata");
|
|
768
|
+
else packuments.set(packageName, result);
|
|
769
|
+
} catch (error) {
|
|
770
|
+
failures.set(packageName, sanitizeRegistryError(error));
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
await Promise.all(Array.from({ length: Math.min(8, names.length) }, worker));
|
|
775
|
+
return {
|
|
776
|
+
packuments,
|
|
777
|
+
failures
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
//#endregion
|
|
781
|
+
//#region src/update/writer.ts
|
|
782
|
+
function groupEdits(edits) {
|
|
783
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
784
|
+
for (const edit of edits) {
|
|
785
|
+
const entries = grouped.get(edit.manifestPath) ?? [];
|
|
786
|
+
entries.push(edit);
|
|
787
|
+
grouped.set(edit.manifestPath, entries);
|
|
788
|
+
}
|
|
789
|
+
for (const entries of grouped.values()) entries.sort((left, right) => left.section.localeCompare(right.section) || left.package.localeCompare(right.package));
|
|
790
|
+
return new Map([...grouped].sort(([left], [right]) => left.localeCompare(right)));
|
|
791
|
+
}
|
|
792
|
+
function renderReplacement(source, edits) {
|
|
793
|
+
const errors = [];
|
|
794
|
+
const manifest = parse(source, errors, { allowTrailingComma: true });
|
|
795
|
+
if (errors.length > 0 || !manifest || typeof manifest !== "object" || Array.isArray(manifest)) throw new Error("Manifest changed to invalid JSON before writing.");
|
|
796
|
+
let result = source;
|
|
797
|
+
for (const edit of edits) {
|
|
798
|
+
const dependencies = manifest[edit.section];
|
|
799
|
+
if ((dependencies && typeof dependencies === "object" && !Array.isArray(dependencies) ? dependencies[edit.package] : void 0) !== edit.currentSpecification) throw new Error(`Manifest changed before writing: ${edit.manifestPath}`);
|
|
800
|
+
result = applyEdits(result, modify(result, [edit.section, edit.package], edit.proposedSpecification, {}));
|
|
801
|
+
}
|
|
802
|
+
return result;
|
|
803
|
+
}
|
|
804
|
+
async function cleanup(paths) {
|
|
805
|
+
await Promise.all(paths.map((filePath) => fs.rm(filePath, { force: true }).catch(() => void 0)));
|
|
806
|
+
}
|
|
807
|
+
async function rollback(replaced) {
|
|
808
|
+
let complete = true;
|
|
809
|
+
for (const staged of [...replaced].reverse()) {
|
|
810
|
+
const rollbackPath = path.join(path.dirname(staged.manifestPath), `.${path.basename(staged.manifestPath)}.askr-rollback-${randomUUID()}`);
|
|
811
|
+
try {
|
|
812
|
+
await fs.writeFile(rollbackPath, staged.original, {
|
|
813
|
+
flag: "wx",
|
|
814
|
+
mode: staged.mode
|
|
815
|
+
});
|
|
816
|
+
await fs.rename(rollbackPath, staged.manifestPath);
|
|
817
|
+
} catch {
|
|
818
|
+
complete = false;
|
|
819
|
+
await fs.rm(rollbackPath, { force: true }).catch(() => void 0);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
return complete;
|
|
823
|
+
}
|
|
824
|
+
async function writeManifestEdits(edits, options = {}) {
|
|
825
|
+
if (edits.length === 0) return 0;
|
|
826
|
+
const staged = [];
|
|
827
|
+
const replace = options.replace ?? fs.rename;
|
|
828
|
+
try {
|
|
829
|
+
for (const [manifestPath, manifestEdits] of groupEdits(edits)) {
|
|
830
|
+
const [original, stat] = await Promise.all([fs.readFile(manifestPath), fs.stat(manifestPath)]);
|
|
831
|
+
const replacement = renderReplacement(original.toString("utf8"), manifestEdits);
|
|
832
|
+
const temporaryPath = path.join(path.dirname(manifestPath), `.${path.basename(manifestPath)}.askr-update-${randomUUID()}`);
|
|
833
|
+
await fs.writeFile(temporaryPath, replacement, {
|
|
834
|
+
flag: "wx",
|
|
835
|
+
mode: stat.mode
|
|
836
|
+
});
|
|
837
|
+
staged.push({
|
|
838
|
+
manifestPath,
|
|
839
|
+
original,
|
|
840
|
+
replacement,
|
|
841
|
+
temporaryPath,
|
|
842
|
+
mode: stat.mode
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
} catch (error) {
|
|
846
|
+
await cleanup(staged.map((entry) => entry.temporaryPath));
|
|
847
|
+
throw error;
|
|
848
|
+
}
|
|
849
|
+
const replaced = [];
|
|
850
|
+
try {
|
|
851
|
+
for (const manifest of staged) {
|
|
852
|
+
await replace(manifest.temporaryPath, manifest.manifestPath);
|
|
853
|
+
replaced.push(manifest);
|
|
854
|
+
}
|
|
855
|
+
} catch {
|
|
856
|
+
const rollbackComplete = await rollback(replaced);
|
|
857
|
+
await cleanup(staged.map((entry) => entry.temporaryPath));
|
|
858
|
+
throw new Error(rollbackComplete ? "Manifest replacement failed; completed replacements were rolled back." : "Manifest replacement failed and rollback was incomplete.");
|
|
859
|
+
}
|
|
860
|
+
return edits.length;
|
|
861
|
+
}
|
|
862
|
+
//#endregion
|
|
863
|
+
//#region src/bin/update.ts
|
|
864
|
+
function helpText() {
|
|
865
|
+
return [
|
|
866
|
+
"askr update - Plan or apply dependency manifest updates",
|
|
867
|
+
"",
|
|
868
|
+
"Usage:",
|
|
869
|
+
" askr update [packages...] [options]",
|
|
870
|
+
"",
|
|
871
|
+
"Options:",
|
|
872
|
+
" -u, --upgrade Apply compatible package.json edits",
|
|
873
|
+
" -f, --force Include breaking updates (requires --upgrade)",
|
|
874
|
+
" --cwd <dir> Resolve a project from another directory",
|
|
875
|
+
" --workspace <glob> Select workspace names (repeatable)",
|
|
876
|
+
" --tag <tag> Use one registry dist-tag for selected packages",
|
|
877
|
+
" --json Emit one deterministic JSON object on stdout",
|
|
878
|
+
" --help, -h Show this help message",
|
|
879
|
+
"",
|
|
880
|
+
"Notes:",
|
|
881
|
+
" Package arguments are minimatch patterns and override persistent ignores.",
|
|
882
|
+
" The command is dry-run by default and changes package.json files only.",
|
|
883
|
+
" Lockfiles, installs, and lifecycle scripts are never touched."
|
|
884
|
+
].join("\n");
|
|
885
|
+
}
|
|
886
|
+
function optionValue(args, index, option, errors) {
|
|
887
|
+
if (index + 1 >= args.length || args[index + 1].startsWith("-")) {
|
|
888
|
+
errors.push(`Missing value for ${option}`);
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
891
|
+
return args[index + 1];
|
|
892
|
+
}
|
|
893
|
+
function parseArgs(args) {
|
|
894
|
+
const parsed = {
|
|
895
|
+
cwd: process.cwd(),
|
|
896
|
+
force: false,
|
|
897
|
+
help: false,
|
|
898
|
+
json: false,
|
|
899
|
+
packagePatterns: [],
|
|
900
|
+
upgrade: false,
|
|
901
|
+
workspacePatterns: [],
|
|
902
|
+
errors: []
|
|
903
|
+
};
|
|
904
|
+
let positionalOnly = false;
|
|
905
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
906
|
+
const argument = args[index];
|
|
907
|
+
if (positionalOnly) parsed.packagePatterns.push(argument);
|
|
908
|
+
else if (argument === "--") positionalOnly = true;
|
|
909
|
+
else if (argument === "--help" || argument === "-h") parsed.help = true;
|
|
910
|
+
else if (argument === "--upgrade" || argument === "-u") parsed.upgrade = true;
|
|
911
|
+
else if (argument === "--force" || argument === "-f") parsed.force = true;
|
|
912
|
+
else if (argument === "--json") parsed.json = true;
|
|
913
|
+
else if (argument === "--cwd") {
|
|
914
|
+
const value = optionValue(args, index, "--cwd", parsed.errors);
|
|
915
|
+
if (value !== null) {
|
|
916
|
+
parsed.cwd = path.resolve(value);
|
|
917
|
+
index += 1;
|
|
918
|
+
}
|
|
919
|
+
} else if (argument.startsWith("--cwd=")) parsed.cwd = path.resolve(argument.slice(6));
|
|
920
|
+
else if (argument === "--workspace") {
|
|
921
|
+
const value = optionValue(args, index, "--workspace", parsed.errors);
|
|
922
|
+
if (value !== null) {
|
|
923
|
+
parsed.workspacePatterns.push(value);
|
|
924
|
+
index += 1;
|
|
925
|
+
}
|
|
926
|
+
} else if (argument.startsWith("--workspace=")) parsed.workspacePatterns.push(argument.slice(12));
|
|
927
|
+
else if (argument === "--tag") {
|
|
928
|
+
const value = optionValue(args, index, "--tag", parsed.errors);
|
|
929
|
+
if (value !== null) {
|
|
930
|
+
parsed.tag = value;
|
|
931
|
+
index += 1;
|
|
932
|
+
}
|
|
933
|
+
} else if (argument.startsWith("--tag=")) parsed.tag = argument.slice(6);
|
|
934
|
+
else if (argument.startsWith("-")) parsed.errors.push(`Unknown option: ${argument}`);
|
|
935
|
+
else parsed.packagePatterns.push(argument);
|
|
936
|
+
}
|
|
937
|
+
if (parsed.force && !parsed.upgrade) parsed.errors.push("--force requires --upgrade");
|
|
938
|
+
if (parsed.tag !== void 0 && (!parsed.tag || /\s/.test(parsed.tag))) parsed.errors.push("--tag must be a non-empty dist-tag without whitespace");
|
|
939
|
+
if (parsed.workspacePatterns.some((pattern) => !pattern)) parsed.errors.push("--workspace patterns must not be empty");
|
|
940
|
+
if (parsed.packagePatterns.some((pattern) => !pattern)) parsed.errors.push("Package patterns must not be empty");
|
|
941
|
+
return parsed;
|
|
942
|
+
}
|
|
943
|
+
function emptySummary() {
|
|
944
|
+
return {
|
|
945
|
+
packages: 0,
|
|
946
|
+
occurrences: 0,
|
|
947
|
+
changedOccurrences: 0,
|
|
948
|
+
current: 0,
|
|
949
|
+
safe: 0,
|
|
950
|
+
breaking: 0,
|
|
951
|
+
local: 0,
|
|
952
|
+
manual: 0,
|
|
953
|
+
error: 0
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
function serializableDecision(decision) {
|
|
957
|
+
return {
|
|
958
|
+
package: decision.package,
|
|
959
|
+
selectedTag: decision.selectedTag,
|
|
960
|
+
targetVersion: decision.targetVersion,
|
|
961
|
+
status: decision.status,
|
|
962
|
+
reason: decision.reason,
|
|
963
|
+
occurrences: decision.occurrences.map((occurrence) => ({
|
|
964
|
+
workspace: occurrence.workspace,
|
|
965
|
+
manifest: occurrence.relativeManifestPath,
|
|
966
|
+
section: occurrence.section,
|
|
967
|
+
currentSpecification: occurrence.currentSpecification,
|
|
968
|
+
proposedSpecification: occurrence.proposedSpecification,
|
|
969
|
+
allowedVersion: occurrence.allowedVersion,
|
|
970
|
+
status: occurrence.status,
|
|
971
|
+
reason: occurrence.reason
|
|
972
|
+
}))
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function selectedWorkspaceJson(root, workspaces) {
|
|
976
|
+
return workspaces.map((workspace) => ({
|
|
977
|
+
name: workspace.name,
|
|
978
|
+
path: path.relative(root, workspace.directory).split(path.sep).join("/") || ".",
|
|
979
|
+
manifest: workspace.relativeManifestPath
|
|
980
|
+
}));
|
|
981
|
+
}
|
|
982
|
+
function emitJson(io, options) {
|
|
983
|
+
io.log(JSON.stringify({
|
|
984
|
+
root: options.root,
|
|
985
|
+
workspaces: options.workspaces,
|
|
986
|
+
summary: options.summary,
|
|
987
|
+
decisions: options.decisions.map(serializableDecision),
|
|
988
|
+
applied: { occurrences: options.applied },
|
|
989
|
+
errors: options.errors
|
|
990
|
+
}, null, 2));
|
|
991
|
+
}
|
|
992
|
+
function rangeText(occurrence) {
|
|
993
|
+
if (occurrence.proposedSpecification) return `${occurrence.currentSpecification} → ${occurrence.proposedSpecification}`;
|
|
994
|
+
if (occurrence.status === "breaking") return `${occurrence.currentSpecification} (skipped; use -u -f)`;
|
|
995
|
+
return `${occurrence.currentSpecification} (${occurrence.reason})`;
|
|
996
|
+
}
|
|
997
|
+
function renderTable(rows) {
|
|
998
|
+
const headings = [
|
|
999
|
+
"Package",
|
|
1000
|
+
"Allowed",
|
|
1001
|
+
"Latest",
|
|
1002
|
+
"Status",
|
|
1003
|
+
"Range"
|
|
1004
|
+
];
|
|
1005
|
+
const widths = headings.map((heading, column) => Math.max(heading.length, ...rows.map((row) => row[column].length)));
|
|
1006
|
+
return [headings, ...rows].map((row) => row.map((value, column) => column === row.length - 1 ? value : value.padEnd(widths[column])).join(" "));
|
|
1007
|
+
}
|
|
1008
|
+
function emitHuman(io, decisions, summary, applied, upgrade) {
|
|
1009
|
+
const byWorkspace = /* @__PURE__ */ new Map();
|
|
1010
|
+
for (const decision of decisions) for (const occurrence of decision.occurrences) {
|
|
1011
|
+
if (occurrence.status === "current") continue;
|
|
1012
|
+
const rows = byWorkspace.get(occurrence.workspace) ?? [];
|
|
1013
|
+
rows.push([
|
|
1014
|
+
decision.package,
|
|
1015
|
+
occurrence.allowedVersion ?? "-",
|
|
1016
|
+
decision.targetVersion ?? "-",
|
|
1017
|
+
occurrence.status,
|
|
1018
|
+
rangeText(occurrence)
|
|
1019
|
+
]);
|
|
1020
|
+
byWorkspace.set(occurrence.workspace, rows);
|
|
1021
|
+
}
|
|
1022
|
+
if (byWorkspace.size === 0) io.log("All selected dependencies are current.");
|
|
1023
|
+
else {
|
|
1024
|
+
let first = true;
|
|
1025
|
+
for (const [workspace, rows] of byWorkspace) {
|
|
1026
|
+
if (!first) io.log("");
|
|
1027
|
+
first = false;
|
|
1028
|
+
io.log(workspace);
|
|
1029
|
+
for (const line of renderTable(rows)) io.log(line);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
const counts = [
|
|
1033
|
+
"safe",
|
|
1034
|
+
"breaking",
|
|
1035
|
+
"current",
|
|
1036
|
+
"manual",
|
|
1037
|
+
"local",
|
|
1038
|
+
"error"
|
|
1039
|
+
].filter((status) => summary[status] > 0).map((status) => `${summary[status]} ${status}`).join(", ");
|
|
1040
|
+
io.log("");
|
|
1041
|
+
io.log(`Scanned ${summary.packages} package${summary.packages === 1 ? "" : "s"}${counts ? `: ${counts}` : "."}`);
|
|
1042
|
+
if (upgrade) io.log(`Updated ${applied} manifest occurrence${applied === 1 ? "" : "s"}.`);
|
|
1043
|
+
else if (summary.changedOccurrences > 0) io.log(`Dry run: ${summary.changedOccurrences} manifest occurrence${summary.changedOccurrences === 1 ? "" : "s"} can be updated; rerun with -u to apply.`);
|
|
1044
|
+
}
|
|
1045
|
+
function collectEdits(decisions) {
|
|
1046
|
+
return decisions.flatMap((decision) => decision.occurrences.flatMap((occurrence) => occurrence.proposedSpecification ? [{
|
|
1047
|
+
manifestPath: occurrence.manifestPath,
|
|
1048
|
+
section: occurrence.section,
|
|
1049
|
+
package: decision.package,
|
|
1050
|
+
currentSpecification: occurrence.currentSpecification,
|
|
1051
|
+
proposedSpecification: occurrence.proposedSpecification
|
|
1052
|
+
}] : []));
|
|
1053
|
+
}
|
|
1054
|
+
async function defaultRegistry(root, packageNames) {
|
|
1055
|
+
return fetchPackuments(packageNames, await loadNpmConfiguration(root));
|
|
1056
|
+
}
|
|
1057
|
+
async function runUpdateCli(args, io = console, runtime = {}) {
|
|
1058
|
+
const parsed = parseArgs(args);
|
|
1059
|
+
if (parsed.help && parsed.errors.length === 0) {
|
|
1060
|
+
io.log(helpText());
|
|
1061
|
+
return 0;
|
|
1062
|
+
}
|
|
1063
|
+
if (parsed.errors.length > 0) {
|
|
1064
|
+
for (const error of parsed.errors) io.error(`askr update: ${error}`);
|
|
1065
|
+
if (parsed.json) emitJson(io, {
|
|
1066
|
+
root: null,
|
|
1067
|
+
workspaces: [],
|
|
1068
|
+
summary: emptySummary(),
|
|
1069
|
+
decisions: [],
|
|
1070
|
+
applied: 0,
|
|
1071
|
+
errors: parsed.errors
|
|
1072
|
+
});
|
|
1073
|
+
return 1;
|
|
1074
|
+
}
|
|
1075
|
+
let root = null;
|
|
1076
|
+
let selectedWorkspaces = [];
|
|
1077
|
+
try {
|
|
1078
|
+
const project = await discoverProject({
|
|
1079
|
+
cwd: parsed.cwd,
|
|
1080
|
+
packagePatterns: parsed.packagePatterns,
|
|
1081
|
+
workspacePatterns: parsed.workspacePatterns
|
|
1082
|
+
});
|
|
1083
|
+
root = project.root;
|
|
1084
|
+
selectedWorkspaces = project.selectedWorkspaces;
|
|
1085
|
+
const lookupNames = project.occurrences.some((occurrence) => occurrence.kind === "fetch") ? project.contextOccurrences.filter((occurrence) => occurrence.registryManaged).map((occurrence) => occurrence.package) : [];
|
|
1086
|
+
const registry = runtime.registry ?? defaultRegistry;
|
|
1087
|
+
const results = lookupNames.length > 0 ? await registry(project.root, lookupNames) : {
|
|
1088
|
+
packuments: /* @__PURE__ */ new Map(),
|
|
1089
|
+
failures: /* @__PURE__ */ new Map()
|
|
1090
|
+
};
|
|
1091
|
+
const plan = planUpdates({
|
|
1092
|
+
occurrences: project.occurrences,
|
|
1093
|
+
contextOccurrences: project.contextOccurrences,
|
|
1094
|
+
packuments: results.packuments,
|
|
1095
|
+
failures: results.failures,
|
|
1096
|
+
tags: project.policy.tags,
|
|
1097
|
+
cliTag: parsed.tag,
|
|
1098
|
+
force: parsed.force
|
|
1099
|
+
});
|
|
1100
|
+
let applied = 0;
|
|
1101
|
+
const errors = [];
|
|
1102
|
+
if (!plan.hasErrors && parsed.upgrade) try {
|
|
1103
|
+
applied = await (runtime.writer ?? writeManifestEdits)(collectEdits(plan.decisions));
|
|
1104
|
+
} catch {
|
|
1105
|
+
errors.push("Unable to replace package manifests; completed replacements were rolled back when possible.");
|
|
1106
|
+
}
|
|
1107
|
+
if (plan.hasErrors) errors.push("One or more registry lookups or package plans failed.");
|
|
1108
|
+
if (parsed.json) emitJson(io, {
|
|
1109
|
+
root: project.root,
|
|
1110
|
+
workspaces: selectedWorkspaceJson(project.root, project.selectedWorkspaces),
|
|
1111
|
+
summary: plan.summary,
|
|
1112
|
+
decisions: plan.decisions,
|
|
1113
|
+
applied,
|
|
1114
|
+
errors
|
|
1115
|
+
});
|
|
1116
|
+
else emitHuman(io, plan.decisions, plan.summary, applied, parsed.upgrade);
|
|
1117
|
+
for (const error of errors) io.error(`askr update: ${error}`);
|
|
1118
|
+
return errors.length > 0 ? 1 : 0;
|
|
1119
|
+
} catch (error) {
|
|
1120
|
+
const message = error instanceof Error ? error.message : "Update failed.";
|
|
1121
|
+
io.error(`askr update: ${message}`);
|
|
1122
|
+
if (parsed.json) emitJson(io, {
|
|
1123
|
+
root,
|
|
1124
|
+
workspaces: root ? selectedWorkspaceJson(root, selectedWorkspaces) : [],
|
|
1125
|
+
summary: emptySummary(),
|
|
1126
|
+
decisions: [],
|
|
1127
|
+
applied: 0,
|
|
1128
|
+
errors: [message]
|
|
1129
|
+
});
|
|
1130
|
+
return 1;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
async function main() {
|
|
1134
|
+
process.exit(await runUpdateCli(process.argv.slice(2)));
|
|
1135
|
+
}
|
|
1136
|
+
if (isDirectExecution(import.meta.url)) main();
|
|
1137
|
+
//#endregion
|
|
1138
|
+
export { runUpdateCli as t };
|
|
1139
|
+
|
|
1140
|
+
//# sourceMappingURL=update-DyW1na5V.js.map
|