@auraindustry/aurajs 0.0.7 → 0.1.1
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/README.md +98 -2
- package/benchmarks/perf-thresholds.json +54 -0
- package/package.json +4 -7
- package/src/asset-pack.mjs +8 -1
- package/src/authored-project.mjs +1449 -0
- package/src/authored-runtime.mjs +2016 -0
- package/src/authoring/avatar-animation-graph.mjs +648 -0
- package/src/bin-integrity.mjs +272 -0
- package/src/build-contract/assets.mjs +130 -0
- package/src/build-contract/capabilities.mjs +116 -0
- package/src/build-contract/constants.mjs +6 -0
- package/src/build-contract/helpers.mjs +44 -0
- package/src/build-contract/web-templates.mjs +5993 -0
- package/src/build-contract.mjs +27 -2910
- package/src/bundler.mjs +188 -55
- package/src/cli.mjs +4840 -1512
- package/src/commands/project-authoring.mjs +454 -0
- package/src/config.mjs +44 -0
- package/src/conformance/cases/app-and-ui-runtime-cases.mjs +3309 -0
- package/src/conformance/cases/core-runtime-cases.mjs +1431 -0
- package/src/conformance/cases/index.mjs +11 -0
- package/src/conformance/cases/scene3d-and-media-cases.mjs +2094 -0
- package/src/conformance/cases/systems-and-gameplay-cases.mjs +1776 -0
- package/src/conformance/shared.mjs +27 -0
- package/src/conformance-runner.mjs +25 -13
- package/src/conformance.mjs +619 -4020
- package/src/cutscene.mjs +362 -5
- package/src/dev-cli-action.mjs +249 -0
- package/src/dev-cli-inspect.mjs +92 -0
- package/src/dev-cli-state.mjs +80 -0
- package/src/external-asset-cache.mjs +587 -0
- package/src/external-asset-policy.mjs +217 -0
- package/src/external-package-surface.mjs +206 -0
- package/src/game-action-runtime.mjs +869 -0
- package/src/game-state-runtime.mjs +206 -6
- package/src/headless-action.mjs +186 -0
- package/src/headless-test/runtime-animation.mjs +1173 -0
- package/src/headless-test/runtime-coordinator.mjs +1514 -0
- package/src/headless-test/runtime-primitives.mjs +320 -0
- package/src/headless-test/runtime-world.mjs +2253 -0
- package/src/headless-test.mjs +392 -4298
- package/src/host-binary.mjs +342 -14
- package/src/icon-discovery.mjs +64 -0
- package/src/make-catalog.mjs +109 -0
- package/src/make.mjs +197 -0
- package/src/package-integrity.mjs +586 -0
- package/src/perf-benchmark.mjs +353 -0
- package/src/postinstall.mjs +5 -5
- package/src/prefabs/index.mjs +34 -0
- package/src/prefabs/scene-serialization.mjs +184 -0
- package/src/project-importer.mjs +620 -0
- package/src/project-registry.mjs +24 -0
- package/src/publish-command.mjs +195 -0
- package/src/publish-env-example.mjs +83 -0
- package/src/publish-validation.mjs +708 -0
- package/src/retro/assets/compile.mjs +232 -0
- package/src/retro/backend-gba/authoring.mjs +1029 -0
- package/src/retro/backend-gba/rom.mjs +363 -0
- package/src/retro/backend-gbc/rom.mjs +85 -0
- package/src/retro/build.mjs +278 -0
- package/src/retro/cli/commands.mjs +292 -0
- package/src/retro/cli/templates.mjs +84 -0
- package/src/retro/diagnostics/catalog.mjs +110 -0
- package/src/retro/diagnostics/emit.mjs +72 -0
- package/src/retro/emulator/case-overlay.mjs +64 -0
- package/src/retro/emulator/discovery.mjs +158 -0
- package/src/retro/emulator/macos-case-overlay.swift +220 -0
- package/src/retro/emulator/profiles.mjs +146 -0
- package/src/retro/emulator/runner.mjs +289 -0
- package/src/retro/frontend/load-project.mjs +98 -0
- package/src/retro/index.mjs +30 -0
- package/src/retro/ir/build-ir.mjs +108 -0
- package/src/retro/runtime-gba/contract.mjs +151 -0
- package/src/retro/runtime-gbc/contract.mjs +117 -0
- package/src/retro/shared/span.mjs +26 -0
- package/src/retro/shared/targets.mjs +64 -0
- package/src/retro/validator/check-project.mjs +114 -0
- package/src/runtime-hotspot-audit.mjs +707 -0
- package/src/scaffold/config.mjs +1000 -0
- package/src/scaffold/fs.mjs +56 -0
- package/src/scaffold/layout.mjs +318 -0
- package/src/scaffold/project-docs.mjs +439 -0
- package/src/scaffold.mjs +93 -596
- package/src/scene-composition/index.mjs +326 -0
- package/src/scene-composition/runtime.mjs +751 -0
- package/src/self-hosted-assets.mjs +604 -0
- package/src/session-client.mjs +750 -0
- package/src/session-native-launcher.mjs +74 -0
- package/src/session-protocol.mjs +75 -0
- package/src/session-runtime.mjs +321 -0
- package/src/session-server.mjs +360 -0
- package/src/shader-kits/index.mjs +773 -0
- package/src/starter-content-registry.mjs +292 -0
- package/src/state-artifacts.mjs +662 -24
- package/src/state-dev-reload.mjs +99 -2
- package/src/terminal-ui.mjs +245 -0
- package/src/web-conformance.mjs +219 -0
- package/templates/create/2d/config/gameplay/shooter.config.js +26 -0
- package/templates/create/2d/content/gameplay/waves.json +26 -0
- package/templates/create/2d/content/registries/.gitkeep +1 -0
- package/templates/create/2d/docs/design/.gitkeep +1 -0
- package/templates/create/2d/docs/design/loop.md +5 -0
- package/templates/create/2d/prefabs/enemies.prefab.js +90 -0
- package/templates/create/2d/prefabs/enemy-basic.prefab.js +18 -0
- package/templates/create/2d/prefabs/player.prefab.js +36 -0
- package/templates/create/2d/prefabs/projectiles.prefab.js +35 -0
- package/templates/create/2d/scenes/boot.scene.js +12 -0
- package/templates/create/2d/scenes/gameplay.scene.js +230 -0
- package/templates/create/2d/scenes/menu.scene.js +9 -0
- package/templates/create/2d/src/main.js +6 -185
- package/templates/create/2d/src/runtime/app.js +49 -0
- package/templates/create/2d/src/runtime/capabilities.js +35 -0
- package/templates/create/2d/ui/hud.screen.js +40 -0
- package/templates/create/2d/ui/pause.screen.js +149 -0
- package/templates/create/2d/ui/settings.screen.js +347 -0
- package/templates/create/2d/ui/title.screen.js +13 -0
- package/templates/create/2d-adventure/aura.config.json +28 -0
- package/templates/create/2d-adventure/config/gameplay/adventure.config.js +14 -0
- package/templates/create/2d-adventure/content/gameplay/world.js +46 -0
- package/templates/create/2d-adventure/content/registries/.gitkeep +1 -0
- package/templates/create/2d-adventure/docs/design/loop.md +5 -0
- package/templates/create/2d-adventure/prefabs/player.prefab.js +54 -0
- package/templates/create/2d-adventure/prefabs/relic.prefab.js +38 -0
- package/templates/create/2d-adventure/prefabs/world.prefab.js +125 -0
- package/templates/create/2d-adventure/scenes/gameplay.scene.js +256 -0
- package/templates/create/2d-adventure/src/runtime/capabilities.js +34 -0
- package/templates/create/2d-adventure/ui/hud.screen.js +60 -0
- package/templates/create/2d-survivor/config/gameplay/survivor.config.js +33 -0
- package/templates/create/2d-survivor/content/gameplay/spawn-zones.json +29 -0
- package/templates/create/2d-survivor/content/registries/.gitkeep +1 -0
- package/templates/create/2d-survivor/docs/design/.gitkeep +1 -0
- package/templates/create/2d-survivor/docs/design/loop.md +5 -0
- package/templates/create/2d-survivor/prefabs/enemies.prefab.js +178 -0
- package/templates/create/2d-survivor/prefabs/enemy-swarm.prefab.js +18 -0
- package/templates/create/2d-survivor/prefabs/player.prefab.js +42 -0
- package/templates/create/2d-survivor/prefabs/projectiles.prefab.js +56 -0
- package/templates/create/2d-survivor/scenes/boot.scene.js +12 -0
- package/templates/create/2d-survivor/scenes/gameplay.scene.js +314 -0
- package/templates/create/2d-survivor/scenes/menu.scene.js +9 -0
- package/templates/create/2d-survivor/src/main.js +5 -332
- package/templates/create/2d-survivor/src/runtime/app.js +49 -0
- package/templates/create/2d-survivor/src/runtime/capabilities.js +35 -0
- package/templates/create/2d-survivor/ui/hud.screen.js +45 -0
- package/templates/create/2d-survivor/ui/title.screen.js +13 -0
- package/templates/create/3d/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d/config/gameplay/.gitkeep +1 -0
- package/templates/create/3d/content/gameplay/checkpoints.json +33 -0
- package/templates/create/3d/content/gameplay/course.js +40 -0
- package/templates/create/3d/content/registries/.gitkeep +1 -0
- package/templates/create/3d/docs/design/.gitkeep +1 -0
- package/templates/create/3d/docs/design/loop.md +5 -0
- package/templates/create/3d/prefabs/checkpoint.prefab.js +15 -0
- package/templates/create/3d/prefabs/player.prefab.js +204 -0
- package/templates/create/3d/prefabs/world.prefab.js +112 -0
- package/templates/create/3d/scenes/boot.scene.js +12 -0
- package/templates/create/3d/scenes/checkpoint.scene.js +9 -0
- package/templates/create/3d/scenes/gameplay.scene.js +292 -0
- package/templates/create/3d/src/main.js +6 -295
- package/templates/create/3d/src/runtime/app.js +49 -0
- package/templates/create/3d/src/runtime/capabilities.js +53 -0
- package/templates/create/3d/src/runtime/materials.js +34 -0
- package/templates/create/3d/src/runtime/state.js +39 -0
- package/templates/create/3d/ui/hud.screen.js +75 -0
- package/templates/create/3d/ui/pause.screen.js +166 -0
- package/templates/create/3d/ui/settings.screen.js +387 -0
- package/templates/create/3d-adventure/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d-adventure/aura.config.json +28 -0
- package/templates/create/3d-adventure/config/gameplay/adventure.config.js +9 -0
- package/templates/create/3d-adventure/content/gameplay/course.js +62 -0
- package/templates/create/3d-adventure/content/registries/.gitkeep +1 -0
- package/templates/create/3d-adventure/docs/design/loop.md +5 -0
- package/templates/create/3d-adventure/prefabs/player.prefab.js +168 -0
- package/templates/create/3d-adventure/prefabs/relic.prefab.js +35 -0
- package/templates/create/3d-adventure/prefabs/world.prefab.js +119 -0
- package/templates/create/3d-adventure/scenes/gameplay.scene.js +358 -0
- package/templates/create/3d-adventure/src/runtime/capabilities.js +56 -0
- package/templates/create/3d-adventure/src/runtime/materials.js +39 -0
- package/templates/create/3d-adventure/src/runtime/state.js +31 -0
- package/templates/create/3d-adventure/ui/hud.screen.js +70 -0
- package/templates/create/3d-adventure/ui/pause.screen.js +437 -0
- package/templates/create/3d-collectathon/assets/models/starter-avatar.gltf +184 -0
- package/templates/create/3d-collectathon/config/gameplay/.gitkeep +1 -0
- package/templates/create/3d-collectathon/content/gameplay/collectibles.json +26 -0
- package/templates/create/3d-collectathon/content/gameplay/course.js +46 -0
- package/templates/create/3d-collectathon/content/registries/.gitkeep +1 -0
- package/templates/create/3d-collectathon/docs/design/.gitkeep +1 -0
- package/templates/create/3d-collectathon/docs/design/loop.md +5 -0
- package/templates/create/3d-collectathon/prefabs/collectible.prefab.js +15 -0
- package/templates/create/3d-collectathon/prefabs/player.prefab.js +207 -0
- package/templates/create/3d-collectathon/prefabs/world.prefab.js +112 -0
- package/templates/create/3d-collectathon/scenes/boot.scene.js +12 -0
- package/templates/create/3d-collectathon/scenes/checkpoint.scene.js +9 -0
- package/templates/create/3d-collectathon/scenes/gameplay.scene.js +200 -0
- package/templates/create/3d-collectathon/src/main.js +5 -355
- package/templates/create/3d-collectathon/src/runtime/app.js +49 -0
- package/templates/create/3d-collectathon/src/runtime/capabilities.js +53 -0
- package/templates/create/3d-collectathon/src/runtime/materials.js +34 -0
- package/templates/create/3d-collectathon/src/runtime/state.js +27 -0
- package/templates/create/3d-collectathon/ui/hud.screen.js +66 -0
- package/templates/create/3d-collectathon/ui/pause.screen.js +13 -0
- package/templates/create/blank/config/gameplay/.gitkeep +1 -0
- package/templates/create/blank/content/gameplay/.gitkeep +1 -0
- package/templates/create/blank/content/registries/.gitkeep +1 -0
- package/templates/create/blank/docs/design/.gitkeep +1 -0
- package/templates/create/blank/docs/design/loop.md +5 -0
- package/templates/create/blank/prefabs/.gitkeep +1 -0
- package/templates/create/blank/scenes/.gitkeep +1 -0
- package/templates/create/blank/src/runtime/.gitkeep +1 -0
- package/templates/create/blank/ui/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/audio/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/fonts/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/sprites/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/assets/starter/README.md +11 -0
- package/templates/create/deckbuilder-2d/assets/ui/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/aura.config.json +28 -0
- package/templates/create/deckbuilder-2d/config/gameplay/deckbuilder.config.js +26 -0
- package/templates/create/deckbuilder-2d/content/cards/guard.card.js +19 -0
- package/templates/create/deckbuilder-2d/content/cards/spark.card.js +20 -0
- package/templates/create/deckbuilder-2d/content/cards/starter.deck.js +69 -0
- package/templates/create/deckbuilder-2d/content/cards/strike.card.js +19 -0
- package/templates/create/deckbuilder-2d/content/cards/survey.card.js +20 -0
- package/templates/create/deckbuilder-2d/content/encounters/training-battle.encounter.js +14 -0
- package/templates/create/deckbuilder-2d/content/encounters/training-battle.js +65 -0
- package/templates/create/deckbuilder-2d/content/enemies/training-automaton.enemy.js +48 -0
- package/templates/create/deckbuilder-2d/content/gameplay/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/content/registries/cards.registry.js +26 -0
- package/templates/create/deckbuilder-2d/content/registries/encounters.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/registries/enemies.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/registries/relics.registry.js +20 -0
- package/templates/create/deckbuilder-2d/content/relics/ember-charm.relic.js +18 -0
- package/templates/create/deckbuilder-2d/docs/design/loop.md +12 -0
- package/templates/create/deckbuilder-2d/prefabs/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/scenes/boot.scene.js +84 -0
- package/templates/create/deckbuilder-2d/scenes/gameplay.scene.js +641 -0
- package/templates/create/deckbuilder-2d/src/components/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/src/main.js +17 -0
- package/templates/create/deckbuilder-2d/src/runtime/capabilities.js +22 -0
- package/templates/create/deckbuilder-2d/src/shared/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/src/systems/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/tests/smoke/.gitkeep +1 -0
- package/templates/create/deckbuilder-2d/ui/hud.screen.js +80 -0
- package/templates/create/deckbuilder-2d/ui/pause.screen.js +146 -0
- package/templates/create/deckbuilder-2d/ui/settings.screen.js +342 -0
- package/templates/create/local-multiplayer/aura.config.json +41 -0
- package/templates/create/local-multiplayer/config/gameplay/local-multiplayer.config.js +26 -0
- package/templates/create/local-multiplayer/content/gameplay/room-layout.js +13 -0
- package/templates/create/local-multiplayer/content/registries/.gitkeep +1 -0
- package/templates/create/local-multiplayer/docs/design/loop.md +16 -0
- package/templates/create/local-multiplayer/prefabs/player.prefab.js +99 -0
- package/templates/create/local-multiplayer/scenes/boot.scene.js +12 -0
- package/templates/create/local-multiplayer/scenes/gameplay.scene.js +472 -0
- package/templates/create/local-multiplayer/src/main.js +17 -0
- package/templates/create/local-multiplayer/src/runtime/capabilities.js +28 -0
- package/templates/create/local-multiplayer/ui/hud.screen.js +65 -0
- package/templates/create/shared/src/runtime/project-inspector.js +105 -0
- package/templates/create/shared/src/runtime/scene-flow.js +290 -0
- package/templates/create/shared/src/runtime/screen-shell.js +222 -0
- package/templates/create/shared/src/runtime/ui-forms.js +209 -0
- package/templates/create/shared/src/runtime/ui-settings.js +237 -0
- package/templates/create/shared/src/runtime/ui-theme.js +352 -0
- package/templates/create/shared/src/starter-utils/adventure-objectives.js +102 -0
- package/templates/create/shared/src/starter-utils/animation-2d.js +337 -0
- package/templates/create/shared/src/starter-utils/avatar-3d.js +404 -0
- package/templates/create/shared/src/starter-utils/combat-feedback-2d.js +320 -0
- package/templates/create/shared/src/starter-utils/core.js +39 -3
- package/templates/create/shared/src/starter-utils/index.js +8 -2
- package/templates/create/shared/src/starter-utils/platformer-3d.js +34 -3
- package/templates/create/shared/src/starter-utils/triggers.js +662 -0
- package/templates/create/shared/src/starter-utils/tween-2d.js +615 -0
- package/templates/create/video-cutscene/assets/video/.gitkeep +0 -0
- package/templates/create/video-cutscene/aura.config.json +28 -0
- package/templates/create/video-cutscene/config/gameplay/.gitkeep +0 -0
- package/templates/create/video-cutscene/content/gameplay/.gitkeep +0 -0
- package/templates/create/video-cutscene/content/registries/.gitkeep +0 -0
- package/templates/create/video-cutscene/docs/design/loop.md +22 -0
- package/templates/create/video-cutscene/prefabs/.gitkeep +0 -0
- package/templates/create/video-cutscene/scenes/boot.scene.js +11 -0
- package/templates/create/video-cutscene/scenes/cutscene.scene.js +113 -0
- package/templates/create/video-cutscene/scenes/gameplay.scene.js +50 -0
- package/templates/create/video-cutscene/src/main.js +17 -0
- package/templates/create/video-cutscene/src/runtime/app.js +52 -0
- package/templates/create/video-cutscene/src/runtime/capabilities.js +35 -0
- package/templates/create/video-cutscene/src/runtime/state.js +13 -0
- package/templates/create/video-cutscene/ui/.gitkeep +0 -0
- package/templates/create-bin/play.js +1192 -0
- package/templates/make/README.md +46 -0
- package/templates/make/catalog.json +51 -0
- package/templates/make/component/files/{{MAKE_NAME}}.component.js +20 -0
- package/templates/make/component/manifest.json +9 -0
- package/templates/make/data/files/{{MAKE_NAME}}.json +14 -0
- package/templates/make/data/manifest.json +9 -0
- package/templates/make/material/files/{{MAKE_NAME}}.material.json +17 -0
- package/templates/make/material/manifest.json +9 -0
- package/templates/make/prefab/files/{{MAKE_NAME}}.prefab.js +20 -0
- package/templates/make/prefab/manifest.json +9 -0
- package/templates/make/scene/files/{{MAKE_NAME}}.scene.js +31 -0
- package/templates/make/scene/manifest.json +9 -0
- package/templates/make/shader/files/{{MAKE_NAME}}.shader.js +23 -0
- package/templates/make/shader/manifest.json +9 -0
- package/templates/make/system/files/{{MAKE_NAME}}.system.js +15 -0
- package/templates/make/system/manifest.json +9 -0
- package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.js +16 -0
- package/templates/make/ui-screen/files/{{MAKE_NAME}}.screen.json +23 -0
- package/templates/make/ui-screen/manifest.json +10 -0
- package/templates/make-starters/deckbuilder-2d/card/files/{{MAKE_NAME}}.card.js +22 -0
- package/templates/make-starters/deckbuilder-2d/card/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/catalog.json +34 -0
- package/templates/make-starters/deckbuilder-2d/encounter/files/{{MAKE_NAME}}.encounter.js +18 -0
- package/templates/make-starters/deckbuilder-2d/encounter/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/enemy/files/{{MAKE_NAME}}.enemy.js +28 -0
- package/templates/make-starters/deckbuilder-2d/enemy/manifest.json +9 -0
- package/templates/make-starters/deckbuilder-2d/relic/files/{{MAKE_NAME}}.relic.js +23 -0
- package/templates/make-starters/deckbuilder-2d/relic/manifest.json +9 -0
- package/templates/retro/platformer/README.md +10 -0
- package/templates/retro/platformer/assets/retro/assets.json +91 -0
- package/templates/retro/platformer/aura.config.json +7 -0
- package/templates/retro/platformer/package.json +5 -0
- package/templates/retro/platformer/src/main.js +40 -0
- package/templates/retro/puzzle-grid/README.md +10 -0
- package/templates/retro/puzzle-grid/assets/retro/assets.json +90 -0
- package/templates/retro/puzzle-grid/aura.config.json +7 -0
- package/templates/retro/puzzle-grid/package.json +5 -0
- package/templates/retro/puzzle-grid/src/main.js +29 -0
- package/templates/retro/tactics-grid/README.md +10 -0
- package/templates/retro/tactics-grid/assets/retro/assets.json +90 -0
- package/templates/retro/tactics-grid/aura.config.json +7 -0
- package/templates/retro/tactics-grid/package.json +5 -0
- package/templates/retro/tactics-grid/src/main.js +35 -0
- package/templates/retro/topdown-adventure/README.md +10 -0
- package/templates/retro/topdown-adventure/assets/retro/assets.json +95 -0
- package/templates/retro/topdown-adventure/aura.config.json +7 -0
- package/templates/retro/topdown-adventure/package.json +5 -0
- package/templates/retro/topdown-adventure/src/main.js +29 -0
- package/templates/skills/aurajs/SKILL.md +61 -5
|
@@ -0,0 +1,708 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
import { assertProjectBinIntegrity, DEFAULT_AURAJS_PACKAGE_ROOT } from './bin-integrity.mjs';
|
|
7
|
+
import { BUILD_MANIFEST_SCHEMA } from './build-contract.mjs';
|
|
8
|
+
import { loadConfig } from './config.mjs';
|
|
9
|
+
import {
|
|
10
|
+
ASSET_MANIFEST_SCHEMA,
|
|
11
|
+
evaluateExternalAssetPolicy,
|
|
12
|
+
} from './external-asset-policy.mjs';
|
|
13
|
+
import {
|
|
14
|
+
inspectPublishPackFiles,
|
|
15
|
+
preparePublishPackageSurface,
|
|
16
|
+
SELF_HOSTED_PACKAGE_SURFACE_MODE,
|
|
17
|
+
} from './external-package-surface.mjs';
|
|
18
|
+
import {
|
|
19
|
+
PACKAGE_INTEGRITY_MANIFEST_PATH,
|
|
20
|
+
PACKAGE_INTEGRITY_PUBLISH_FILES,
|
|
21
|
+
PACKAGE_INTEGRITY_SIGNATURE_PATH,
|
|
22
|
+
writeSignedPackageIntegrityArtifacts,
|
|
23
|
+
} from './package-integrity.mjs';
|
|
24
|
+
import {
|
|
25
|
+
PUBLISH_ENV_EXAMPLE_PATH,
|
|
26
|
+
PUBLISH_SOURCE_ENV_PATH,
|
|
27
|
+
resolvePublishEnvExampleSurface,
|
|
28
|
+
} from './publish-env-example.mjs';
|
|
29
|
+
|
|
30
|
+
export const PUBLISH_REPORT_SCHEMA = 'aurajs.publish-report.v1';
|
|
31
|
+
const CLI_ENTRY_PATH = fileURLToPath(new URL('./cli.mjs', import.meta.url));
|
|
32
|
+
const AURAJS_PACKAGE_VERSION = JSON.parse(readFileSync(resolve(DEFAULT_AURAJS_PACKAGE_ROOT, 'package.json'), 'utf8')).version;
|
|
33
|
+
|
|
34
|
+
export class PublishValidationError extends Error {
|
|
35
|
+
constructor(reasonCode, message, details = {}) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = 'PublishValidationError';
|
|
38
|
+
this.reasonCode = typeof reasonCode === 'string' && reasonCode.length > 0
|
|
39
|
+
? reasonCode
|
|
40
|
+
: 'publish_validation_failed';
|
|
41
|
+
this.details = details && typeof details === 'object' ? details : {};
|
|
42
|
+
this.reportPath = null;
|
|
43
|
+
this.report = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function nowIso() {
|
|
48
|
+
return new Date().toISOString();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function resolveNpmCommand() {
|
|
52
|
+
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function currentPlatformTarget() {
|
|
56
|
+
if (process.platform === 'win32') return 'windows';
|
|
57
|
+
if (process.platform === 'darwin') return 'mac';
|
|
58
|
+
return 'linux';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function pipeChildStream(stream, target, sink) {
|
|
62
|
+
if (!stream) return;
|
|
63
|
+
stream.on('data', (chunk) => {
|
|
64
|
+
const text = String(chunk);
|
|
65
|
+
sink.push(text);
|
|
66
|
+
target?.write?.(chunk);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function runChildProcess(command, args, {
|
|
71
|
+
cwd,
|
|
72
|
+
env,
|
|
73
|
+
stdout = process.stdout,
|
|
74
|
+
stderr = process.stderr,
|
|
75
|
+
failureReasonCode,
|
|
76
|
+
failureMessage,
|
|
77
|
+
} = {}) {
|
|
78
|
+
return new Promise((resolveRun, rejectRun) => {
|
|
79
|
+
const stdoutChunks = [];
|
|
80
|
+
const stderrChunks = [];
|
|
81
|
+
const child = spawn(command, args, {
|
|
82
|
+
cwd,
|
|
83
|
+
env,
|
|
84
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
pipeChildStream(child.stdout, stdout, stdoutChunks);
|
|
88
|
+
pipeChildStream(child.stderr, stderr, stderrChunks);
|
|
89
|
+
|
|
90
|
+
child.on('error', (error) => {
|
|
91
|
+
rejectRun(new PublishValidationError(
|
|
92
|
+
failureReasonCode,
|
|
93
|
+
`${failureMessage}: ${error.message}`,
|
|
94
|
+
{
|
|
95
|
+
command,
|
|
96
|
+
args,
|
|
97
|
+
cwd,
|
|
98
|
+
},
|
|
99
|
+
));
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
child.on('close', (code, signal) => {
|
|
103
|
+
if ((code ?? 1) === 0) {
|
|
104
|
+
resolveRun({
|
|
105
|
+
ok: true,
|
|
106
|
+
code: 0,
|
|
107
|
+
signal: signal ?? null,
|
|
108
|
+
stdout: stdoutChunks.join(''),
|
|
109
|
+
stderr: stderrChunks.join(''),
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
rejectRun(new PublishValidationError(
|
|
115
|
+
failureReasonCode,
|
|
116
|
+
signal
|
|
117
|
+
? `${failureMessage}: process exited by signal ${signal}.`
|
|
118
|
+
: `${failureMessage}: process exited with code ${code ?? 1}.`,
|
|
119
|
+
{
|
|
120
|
+
command,
|
|
121
|
+
args,
|
|
122
|
+
cwd,
|
|
123
|
+
code: code ?? 1,
|
|
124
|
+
signal: signal ?? null,
|
|
125
|
+
stdout: stdoutChunks.join(''),
|
|
126
|
+
stderr: stderrChunks.join(''),
|
|
127
|
+
},
|
|
128
|
+
));
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function readProjectPackage(projectRoot) {
|
|
134
|
+
const packagePath = resolve(projectRoot, 'package.json');
|
|
135
|
+
if (!existsSync(packagePath)) {
|
|
136
|
+
throw new PublishValidationError(
|
|
137
|
+
'publish_package_json_missing',
|
|
138
|
+
'aura publish requires a package.json in the current project root.',
|
|
139
|
+
{ packagePath },
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let projectPackage;
|
|
144
|
+
try {
|
|
145
|
+
projectPackage = JSON.parse(readFileSync(packagePath, 'utf8'));
|
|
146
|
+
} catch (error) {
|
|
147
|
+
throw new PublishValidationError(
|
|
148
|
+
'publish_package_json_invalid',
|
|
149
|
+
`Failed to read package.json for aura publish: ${error.message}`,
|
|
150
|
+
{ packagePath },
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const packageName = typeof projectPackage?.name === 'string' && projectPackage.name.trim().length > 0
|
|
155
|
+
? projectPackage.name.trim()
|
|
156
|
+
: null;
|
|
157
|
+
if (!packageName) {
|
|
158
|
+
throw new PublishValidationError(
|
|
159
|
+
'publish_package_name_missing',
|
|
160
|
+
'aura publish requires package.json -> name to be set.',
|
|
161
|
+
{ packagePath },
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const packageVersion = typeof projectPackage?.version === 'string' && projectPackage.version.trim().length > 0
|
|
166
|
+
? projectPackage.version.trim()
|
|
167
|
+
: null;
|
|
168
|
+
if (!packageVersion) {
|
|
169
|
+
throw new PublishValidationError(
|
|
170
|
+
'publish_package_version_missing',
|
|
171
|
+
'aura publish requires package.json -> version to be set.',
|
|
172
|
+
{ packagePath },
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
packagePath,
|
|
178
|
+
projectPackage,
|
|
179
|
+
packageName,
|
|
180
|
+
packageVersion,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function normalizeBinEntries(projectPackage, packageName) {
|
|
185
|
+
if (typeof projectPackage?.bin === 'string' && projectPackage.bin.trim().length > 0) {
|
|
186
|
+
return [{
|
|
187
|
+
name: packageName.split('/').pop() || packageName,
|
|
188
|
+
relativePath: normalizeRelativePath(projectPackage.bin.trim()),
|
|
189
|
+
}];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const entries = Object.entries(projectPackage?.bin || {})
|
|
193
|
+
.filter(([, value]) => typeof value === 'string' && value.trim().length > 0)
|
|
194
|
+
.map(([name, value]) => ({
|
|
195
|
+
name,
|
|
196
|
+
relativePath: normalizeRelativePath(value.trim()),
|
|
197
|
+
}));
|
|
198
|
+
|
|
199
|
+
if (entries.length === 0) {
|
|
200
|
+
throw new PublishValidationError(
|
|
201
|
+
'publish_bin_missing',
|
|
202
|
+
'aura publish requires package.json -> bin to point at the generated wrapper entrypoint.',
|
|
203
|
+
{},
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return entries;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function normalizeRelativePath(pathLike) {
|
|
211
|
+
return String(pathLike || '')
|
|
212
|
+
.trim()
|
|
213
|
+
.replace(/^[.][\\/]/, '')
|
|
214
|
+
.replaceAll('\\', '/');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function assertRequiredFileExists(projectRoot, relativePath, reasonCode, message) {
|
|
218
|
+
const absolutePath = resolve(projectRoot, relativePath);
|
|
219
|
+
if (!existsSync(absolutePath)) {
|
|
220
|
+
throw new PublishValidationError(reasonCode, message, {
|
|
221
|
+
path: relativePath,
|
|
222
|
+
absolutePath,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
return absolutePath;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function createBaseReport({ projectRoot, packageName, packageVersion }) {
|
|
229
|
+
const normalizedPackageName = typeof packageName === 'string' && packageName.length > 0
|
|
230
|
+
? packageName
|
|
231
|
+
: null;
|
|
232
|
+
return {
|
|
233
|
+
schema: PUBLISH_REPORT_SCHEMA,
|
|
234
|
+
generatedAt: nowIso(),
|
|
235
|
+
projectRoot,
|
|
236
|
+
package: {
|
|
237
|
+
name: normalizedPackageName,
|
|
238
|
+
version: packageVersion,
|
|
239
|
+
scope: normalizedPackageName
|
|
240
|
+
? (normalizedPackageName.startsWith('@') ? 'scoped' : 'unscoped')
|
|
241
|
+
: null,
|
|
242
|
+
},
|
|
243
|
+
summary: {
|
|
244
|
+
pass: false,
|
|
245
|
+
reasonCode: null,
|
|
246
|
+
},
|
|
247
|
+
validation: {
|
|
248
|
+
metadata: {},
|
|
249
|
+
binIntegrity: {},
|
|
250
|
+
packageIntegrity: {},
|
|
251
|
+
build: {},
|
|
252
|
+
assets: {},
|
|
253
|
+
pack: {},
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function writePublishReport(projectRoot, report) {
|
|
259
|
+
const reportRoot = resolve(projectRoot, '.aura', 'publish');
|
|
260
|
+
mkdirSync(reportRoot, { recursive: true });
|
|
261
|
+
const reportPath = join(reportRoot, 'publish-report.json');
|
|
262
|
+
writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
|
|
263
|
+
return reportPath;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function normalizePackFiles(entry) {
|
|
267
|
+
if (!entry || typeof entry !== 'object' || !Array.isArray(entry.files)) {
|
|
268
|
+
throw new PublishValidationError(
|
|
269
|
+
'publish_pack_json_invalid',
|
|
270
|
+
'npm pack --json --dry-run did not return a files payload.',
|
|
271
|
+
{ entry },
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
return entry.files
|
|
275
|
+
.filter((file) => file && typeof file.path === 'string')
|
|
276
|
+
.map((file) => ({
|
|
277
|
+
path: file.path,
|
|
278
|
+
size: Number.isFinite(file.size) ? file.size : null,
|
|
279
|
+
mode: Number.isFinite(file.mode) ? file.mode : null,
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function validatePackRequiredFiles(packFiles, requiredPaths) {
|
|
284
|
+
const packagedPaths = new Set(packFiles.map((entry) => entry.path));
|
|
285
|
+
const missing = requiredPaths.filter((filePath) => !packagedPaths.has(filePath));
|
|
286
|
+
if (missing.length > 0) {
|
|
287
|
+
throw new PublishValidationError(
|
|
288
|
+
'publish_required_file_missing',
|
|
289
|
+
`npm pack payload is missing required publish files: ${missing.join(', ')}`,
|
|
290
|
+
{ missing },
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async function defaultBuildProject({ projectRoot, env, stdout, stderr }) {
|
|
296
|
+
return runChildProcess(
|
|
297
|
+
process.execPath,
|
|
298
|
+
[CLI_ENTRY_PATH, 'build'],
|
|
299
|
+
{
|
|
300
|
+
cwd: projectRoot,
|
|
301
|
+
env,
|
|
302
|
+
stdout,
|
|
303
|
+
stderr,
|
|
304
|
+
failureReasonCode: 'publish_build_failed',
|
|
305
|
+
failureMessage: 'aura publish validation build failed',
|
|
306
|
+
},
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function defaultRunPackDryRun({ projectRoot, packRoot, env }) {
|
|
311
|
+
const pack = await runChildProcess(
|
|
312
|
+
resolveNpmCommand(),
|
|
313
|
+
['pack', '--json', '--dry-run', '--ignore-scripts'],
|
|
314
|
+
{
|
|
315
|
+
cwd: packRoot || projectRoot,
|
|
316
|
+
env,
|
|
317
|
+
stdout: null,
|
|
318
|
+
stderr: null,
|
|
319
|
+
failureReasonCode: 'publish_pack_dry_run_failed',
|
|
320
|
+
failureMessage: 'aura publish pack dry-run failed',
|
|
321
|
+
},
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
let payload;
|
|
325
|
+
try {
|
|
326
|
+
payload = JSON.parse(pack.stdout || '[]');
|
|
327
|
+
} catch (error) {
|
|
328
|
+
throw new PublishValidationError(
|
|
329
|
+
'publish_pack_json_invalid',
|
|
330
|
+
`Failed to parse npm pack --json output: ${error.message}`,
|
|
331
|
+
{ stdout: pack.stdout },
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (!Array.isArray(payload) || payload.length === 0 || !payload[0]) {
|
|
336
|
+
throw new PublishValidationError(
|
|
337
|
+
'publish_pack_json_invalid',
|
|
338
|
+
'npm pack --json --dry-run returned no package payload.',
|
|
339
|
+
{ payload },
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return payload[0];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export async function validatePublishProject(
|
|
347
|
+
{
|
|
348
|
+
projectRoot = process.cwd(),
|
|
349
|
+
env = process.env,
|
|
350
|
+
stdout = process.stdout,
|
|
351
|
+
stderr = process.stderr,
|
|
352
|
+
buildProject = defaultBuildProject,
|
|
353
|
+
runPackDryRun = defaultRunPackDryRun,
|
|
354
|
+
} = {},
|
|
355
|
+
) {
|
|
356
|
+
let packageSurface = null;
|
|
357
|
+
const report = createBaseReport({
|
|
358
|
+
projectRoot,
|
|
359
|
+
packageName: null,
|
|
360
|
+
packageVersion: null,
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
const { packageName, packageVersion, projectPackage } = readProjectPackage(projectRoot);
|
|
365
|
+
report.package.name = packageName;
|
|
366
|
+
report.package.version = packageVersion;
|
|
367
|
+
report.package.scope = packageName.startsWith('@') ? 'scoped' : 'unscoped';
|
|
368
|
+
const config = await loadConfig({ projectRoot, mode: 'build' });
|
|
369
|
+
const binEntries = normalizeBinEntries(projectPackage, packageName);
|
|
370
|
+
const envExampleSurface = resolvePublishEnvExampleSurface({ projectRoot });
|
|
371
|
+
const requiredProjectFiles = [
|
|
372
|
+
'README.md',
|
|
373
|
+
'aura.config.json',
|
|
374
|
+
'aura.capabilities.json',
|
|
375
|
+
'src/main.js',
|
|
376
|
+
...binEntries.map((entry) => entry.relativePath),
|
|
377
|
+
];
|
|
378
|
+
|
|
379
|
+
report.validation.metadata = {
|
|
380
|
+
reasonCode: 'publish_metadata_ok',
|
|
381
|
+
bin: binEntries,
|
|
382
|
+
requiredProjectFiles,
|
|
383
|
+
publishConfig: projectPackage?.publishConfig || null,
|
|
384
|
+
environment: envExampleSurface.metadata,
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
for (const binEntry of binEntries) {
|
|
388
|
+
assertRequiredFileExists(
|
|
389
|
+
projectRoot,
|
|
390
|
+
binEntry.relativePath,
|
|
391
|
+
'publish_bin_target_missing',
|
|
392
|
+
`aura publish requires bin target "${binEntry.relativePath}" to exist.`,
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
for (const requiredFile of requiredProjectFiles) {
|
|
396
|
+
assertRequiredFileExists(
|
|
397
|
+
projectRoot,
|
|
398
|
+
requiredFile,
|
|
399
|
+
'publish_required_project_file_missing',
|
|
400
|
+
`aura publish requires "${requiredFile}" to exist before publishing.`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const binIntegrity = assertProjectBinIntegrity({
|
|
405
|
+
projectRoot,
|
|
406
|
+
projectPackage,
|
|
407
|
+
packageName,
|
|
408
|
+
aurajsPackageRoot: DEFAULT_AURAJS_PACKAGE_ROOT,
|
|
409
|
+
expectedAurajsVersion: AURAJS_PACKAGE_VERSION,
|
|
410
|
+
enforceExactAurajsDependency: true,
|
|
411
|
+
});
|
|
412
|
+
report.validation.binIntegrity = {
|
|
413
|
+
reasonCode: 'publish_bin_integrity_ok',
|
|
414
|
+
...binIntegrity,
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
stdout?.write('\n aura publish: validating project build contract...\n');
|
|
418
|
+
await buildProject({ projectRoot, env, stdout, stderr });
|
|
419
|
+
|
|
420
|
+
const buildTarget = currentPlatformTarget();
|
|
421
|
+
const buildRoot = resolve(projectRoot, config.build.outDir, buildTarget);
|
|
422
|
+
const buildManifestPath = resolve(buildRoot, 'build-manifest.json');
|
|
423
|
+
assertRequiredFileExists(
|
|
424
|
+
projectRoot,
|
|
425
|
+
join(config.build.outDir, buildTarget, 'build-manifest.json'),
|
|
426
|
+
'publish_build_manifest_missing',
|
|
427
|
+
'aura publish validation requires build-manifest.json to be emitted by aura build.',
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
let buildManifest;
|
|
431
|
+
try {
|
|
432
|
+
buildManifest = JSON.parse(readFileSync(buildManifestPath, 'utf8'));
|
|
433
|
+
} catch (error) {
|
|
434
|
+
throw new PublishValidationError(
|
|
435
|
+
'publish_build_manifest_invalid',
|
|
436
|
+
`Failed to parse build manifest emitted during publish validation: ${error.message}`,
|
|
437
|
+
{ buildManifestPath },
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (buildManifest.schema !== BUILD_MANIFEST_SCHEMA) {
|
|
442
|
+
throw new PublishValidationError(
|
|
443
|
+
'publish_build_manifest_schema_invalid',
|
|
444
|
+
`Publish validation expected ${BUILD_MANIFEST_SCHEMA}, got ${buildManifest?.schema || '<missing>'}.`,
|
|
445
|
+
{ buildManifestPath, schema: buildManifest?.schema || null },
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
const bundleRelativePath = String(buildManifest.entrypoint || '');
|
|
450
|
+
const assetsManifestRelativePath = String(buildManifest.assetsManifest || '');
|
|
451
|
+
if (!bundleRelativePath) {
|
|
452
|
+
throw new PublishValidationError(
|
|
453
|
+
'publish_bundle_missing',
|
|
454
|
+
'Publish validation build manifest is missing the bundled entrypoint path.',
|
|
455
|
+
{ buildManifestPath },
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
if (!assetsManifestRelativePath) {
|
|
459
|
+
throw new PublishValidationError(
|
|
460
|
+
'publish_assets_manifest_missing',
|
|
461
|
+
'Publish validation build manifest is missing the assets manifest path.',
|
|
462
|
+
{ buildManifestPath },
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const bundlePath = resolve(buildRoot, bundleRelativePath);
|
|
467
|
+
const assetsManifestPath = resolve(buildRoot, assetsManifestRelativePath);
|
|
468
|
+
assertRequiredFileExists(
|
|
469
|
+
buildRoot,
|
|
470
|
+
bundleRelativePath,
|
|
471
|
+
'publish_bundle_missing',
|
|
472
|
+
'Publish validation could not find the built JS bundle referenced by build-manifest.json.',
|
|
473
|
+
);
|
|
474
|
+
assertRequiredFileExists(
|
|
475
|
+
buildRoot,
|
|
476
|
+
assetsManifestRelativePath,
|
|
477
|
+
'publish_assets_manifest_missing',
|
|
478
|
+
'Publish validation could not find the assets manifest referenced by build-manifest.json.',
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
let assetsManifest;
|
|
482
|
+
try {
|
|
483
|
+
assetsManifest = JSON.parse(readFileSync(assetsManifestPath, 'utf8'));
|
|
484
|
+
} catch (error) {
|
|
485
|
+
throw new PublishValidationError(
|
|
486
|
+
'publish_assets_manifest_invalid',
|
|
487
|
+
`Failed to parse assets manifest emitted during publish validation: ${error.message}`,
|
|
488
|
+
{ assetsManifestPath },
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (assetsManifest?.schema !== ASSET_MANIFEST_SCHEMA) {
|
|
493
|
+
throw new PublishValidationError(
|
|
494
|
+
'publish_assets_manifest_schema_invalid',
|
|
495
|
+
`Publish validation expected ${ASSET_MANIFEST_SCHEMA}, got ${assetsManifest?.schema || '<missing>'}.`,
|
|
496
|
+
{
|
|
497
|
+
assetsManifestPath,
|
|
498
|
+
schema: assetsManifest?.schema || null,
|
|
499
|
+
},
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (config.identity?.icon) {
|
|
504
|
+
if (buildManifest.icon?.status !== 'copied') {
|
|
505
|
+
throw new PublishValidationError(
|
|
506
|
+
'publish_icon_validation_failed',
|
|
507
|
+
'Publish validation expected the configured identity.icon to be copied into build output.',
|
|
508
|
+
{
|
|
509
|
+
configuredIcon: config.identity.icon,
|
|
510
|
+
icon: buildManifest.icon || null,
|
|
511
|
+
},
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
report.validation.build = {
|
|
517
|
+
reasonCode: 'publish_build_ok',
|
|
518
|
+
buildTarget,
|
|
519
|
+
buildRoot,
|
|
520
|
+
buildManifestPath,
|
|
521
|
+
bundlePath,
|
|
522
|
+
assetsManifestPath,
|
|
523
|
+
identity: buildManifest.identity || null,
|
|
524
|
+
icon: buildManifest.icon || null,
|
|
525
|
+
};
|
|
526
|
+
const buildMetadata = {
|
|
527
|
+
buildTarget,
|
|
528
|
+
buildRoot,
|
|
529
|
+
identity: buildManifest.identity || null,
|
|
530
|
+
icon: buildManifest.icon || null,
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
let assetThresholdRecord;
|
|
534
|
+
try {
|
|
535
|
+
assetThresholdRecord = evaluateExternalAssetPolicy({
|
|
536
|
+
projectRoot,
|
|
537
|
+
buildRoot,
|
|
538
|
+
assetsManifestPath,
|
|
539
|
+
assetsManifest,
|
|
540
|
+
assetDir: config.build.assetDir,
|
|
541
|
+
env,
|
|
542
|
+
});
|
|
543
|
+
} catch (error) {
|
|
544
|
+
throw new PublishValidationError(
|
|
545
|
+
'publish_asset_threshold_invalid',
|
|
546
|
+
error?.message || 'Assets manifest or publish threshold configuration is invalid.',
|
|
547
|
+
{},
|
|
548
|
+
);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
try {
|
|
552
|
+
packageSurface = preparePublishPackageSurface({
|
|
553
|
+
projectRoot,
|
|
554
|
+
projectPackage,
|
|
555
|
+
assetDir: config.build.assetDir,
|
|
556
|
+
assetPolicy: assetThresholdRecord,
|
|
557
|
+
generatedFilePaths: PACKAGE_INTEGRITY_PUBLISH_FILES,
|
|
558
|
+
generatedFiles: envExampleSurface.generatedFiles,
|
|
559
|
+
excludedFilePaths: envExampleSurface.excludedFilePaths,
|
|
560
|
+
});
|
|
561
|
+
} catch (error) {
|
|
562
|
+
throw new PublishValidationError(
|
|
563
|
+
'publish_external_assets_surface_invalid',
|
|
564
|
+
error?.message || 'Failed to stage the self-hosted external asset publish surface.',
|
|
565
|
+
{},
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const packageIntegrity = writeSignedPackageIntegrityArtifacts({
|
|
570
|
+
packageRoot: packageSurface.publishRoot,
|
|
571
|
+
signerProjectRoot: projectRoot,
|
|
572
|
+
buildMetadata,
|
|
573
|
+
});
|
|
574
|
+
report.validation.packageIntegrity = {
|
|
575
|
+
reasonCode: 'publish_package_integrity_ok',
|
|
576
|
+
manifestPath: packageIntegrity.manifestPath,
|
|
577
|
+
signaturePath: packageIntegrity.signaturePath,
|
|
578
|
+
schema: packageIntegrity.schema,
|
|
579
|
+
fileCount: packageIntegrity.fileCount,
|
|
580
|
+
signerFingerprint: packageIntegrity.signerFingerprint,
|
|
581
|
+
publishedMetadata: packageIntegrity.publishedMetadata,
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
assetThresholdRecord.packageSurfaceMode = packageSurface.mode;
|
|
585
|
+
assetThresholdRecord.assetPackaging = packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE
|
|
586
|
+
? 'self_hosted'
|
|
587
|
+
: 'embedded';
|
|
588
|
+
report.validation.assets = assetThresholdRecord;
|
|
589
|
+
if (assetThresholdRecord.blocked) {
|
|
590
|
+
throw new PublishValidationError(
|
|
591
|
+
'publish_asset_threshold_exceeded',
|
|
592
|
+
`AuraJS asset payload is ${assetThresholdRecord.assetBytes} bytes, above the npm-first threshold of ${assetThresholdRecord.thresholdBytes} bytes. Self-host the heavy assets on a public HTTPS base URL (for example Cloudflare R2 or S3), generate the external asset config, then publish the slim package.`,
|
|
593
|
+
assetThresholdRecord,
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const packEntry = await runPackDryRun({
|
|
598
|
+
projectRoot,
|
|
599
|
+
packRoot: packageSurface.publishRoot,
|
|
600
|
+
env,
|
|
601
|
+
});
|
|
602
|
+
const packFiles = normalizePackFiles(packEntry);
|
|
603
|
+
const packInspection = inspectPublishPackFiles(packFiles, {
|
|
604
|
+
assetDir: packageSurface.assetDir,
|
|
605
|
+
externalAssetsConfigPath: packageSurface.externalAssetsConfigPath,
|
|
606
|
+
});
|
|
607
|
+
const requiredPackFiles = [
|
|
608
|
+
'package.json',
|
|
609
|
+
'README.md',
|
|
610
|
+
'aura.config.json',
|
|
611
|
+
'aura.capabilities.json',
|
|
612
|
+
...binEntries.map((entry) => entry.relativePath),
|
|
613
|
+
'src/main.js',
|
|
614
|
+
...(packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE
|
|
615
|
+
? [packageSurface.externalAssetsConfigPath]
|
|
616
|
+
: []),
|
|
617
|
+
...PACKAGE_INTEGRITY_PUBLISH_FILES,
|
|
618
|
+
...(envExampleSurface.metadata.generatedExample ? [PUBLISH_ENV_EXAMPLE_PATH] : []),
|
|
619
|
+
];
|
|
620
|
+
validatePackRequiredFiles(packFiles, requiredPackFiles);
|
|
621
|
+
|
|
622
|
+
if (packFiles.some((entry) => entry.path === PUBLISH_SOURCE_ENV_PATH)) {
|
|
623
|
+
throw new PublishValidationError(
|
|
624
|
+
'publish_env_file_included',
|
|
625
|
+
'.env must not be included in the published npm package. AuraJS generates .env.example instead.',
|
|
626
|
+
{},
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
if (packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE && packInspection.includesAssetPayload) {
|
|
631
|
+
throw new PublishValidationError(
|
|
632
|
+
'publish_external_assets_payload_included',
|
|
633
|
+
`Self-hosted external asset packages must omit ${packageSurface.assetDir}/ from the npm tarball.`,
|
|
634
|
+
{
|
|
635
|
+
assetDir: packageSurface.assetDir,
|
|
636
|
+
},
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (packageSurface.mode === SELF_HOSTED_PACKAGE_SURFACE_MODE && !packInspection.includesExternalAssetsConfig) {
|
|
641
|
+
throw new PublishValidationError(
|
|
642
|
+
'publish_external_assets_config_missing_from_pack',
|
|
643
|
+
`${packageSurface.externalAssetsConfigPath} must be present in the slim npm tarball for self-hosted assets.`,
|
|
644
|
+
{
|
|
645
|
+
configPath: packageSurface.externalAssetsConfigPath,
|
|
646
|
+
},
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
report.validation.pack = {
|
|
651
|
+
reasonCode: 'publish_pack_dry_run_ok',
|
|
652
|
+
filename: typeof packEntry.filename === 'string' ? packEntry.filename : null,
|
|
653
|
+
size: Number.isFinite(packEntry.size) ? packEntry.size : null,
|
|
654
|
+
unpackedSize: Number.isFinite(packEntry.unpackedSize) ? packEntry.unpackedSize : null,
|
|
655
|
+
surfaceMode: packageSurface.mode,
|
|
656
|
+
assetDir: packageSurface.assetDir,
|
|
657
|
+
externalAssetsConfigPath: packageSurface.externalAssetsConfigPath,
|
|
658
|
+
assetPayloadIncluded: packInspection.includesAssetPayload,
|
|
659
|
+
externalAssetsConfigIncluded: packInspection.includesExternalAssetsConfig,
|
|
660
|
+
manifestIncluded: packFiles.some((entry) => entry.path === PACKAGE_INTEGRITY_MANIFEST_PATH),
|
|
661
|
+
signatureIncluded: packFiles.some((entry) => entry.path === PACKAGE_INTEGRITY_SIGNATURE_PATH),
|
|
662
|
+
envExampleIncluded: packFiles.some((entry) => entry.path === PUBLISH_ENV_EXAMPLE_PATH),
|
|
663
|
+
sourceEnvIncluded: packFiles.some((entry) => entry.path === PUBLISH_SOURCE_ENV_PATH),
|
|
664
|
+
files: packFiles,
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
report.summary = {
|
|
668
|
+
pass: true,
|
|
669
|
+
reasonCode: 'publish_validation_ok',
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
const reportPath = writePublishReport(projectRoot, report);
|
|
673
|
+
return {
|
|
674
|
+
ok: true,
|
|
675
|
+
packageName: report.package.name,
|
|
676
|
+
packageVersion: report.package.version,
|
|
677
|
+
report,
|
|
678
|
+
reportPath,
|
|
679
|
+
};
|
|
680
|
+
} catch (error) {
|
|
681
|
+
const normalized = error instanceof PublishValidationError
|
|
682
|
+
? error
|
|
683
|
+
: new PublishValidationError(
|
|
684
|
+
typeof error?.reasonCode === 'string' && error.reasonCode.length > 0
|
|
685
|
+
? error.reasonCode
|
|
686
|
+
: 'publish_validation_failed',
|
|
687
|
+
error?.message || 'Publish validation failed.',
|
|
688
|
+
error?.details && typeof error.details === 'object' ? error.details : {},
|
|
689
|
+
);
|
|
690
|
+
|
|
691
|
+
report.summary = {
|
|
692
|
+
pass: false,
|
|
693
|
+
reasonCode: normalized.reasonCode,
|
|
694
|
+
};
|
|
695
|
+
report.failure = {
|
|
696
|
+
reasonCode: normalized.reasonCode,
|
|
697
|
+
message: normalized.message,
|
|
698
|
+
details: normalized.details,
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
const reportPath = writePublishReport(projectRoot, report);
|
|
702
|
+
normalized.reportPath = reportPath;
|
|
703
|
+
normalized.report = report;
|
|
704
|
+
throw normalized;
|
|
705
|
+
} finally {
|
|
706
|
+
packageSurface?.cleanup?.();
|
|
707
|
+
}
|
|
708
|
+
}
|