mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-07-16 13:55:21 +00:00
* fix(deps): require invoiceshelf/modules ^3.0.2 (adds registerExchangeRateDriver)
DriverRegistryProvider::registerExchangeRateDrivers() calls
Registry::registerExchangeRateDriver(), which only exists in
invoiceshelf/modules >= 3.0.2. The constraint (^3.0) and the committed
lock (3.0.1) allowed/pinned versions without it, so a fresh
`composer install` (CI, Docker, new clones) boots into:
Call to undefined method InvoiceShelf\Modules\Registry::registerExchangeRateDriver()
Pin to ^3.0.2 and update the lock so every install gets a version that
has the method. `php artisan package:discover` verified clean.
* fix(ai): register the AI driver via the generic Registry::registerDriver('ai', ...)
registerAiDriver() is a convenience wrapper that is NOT present in any
published invoiceshelf/modules release (only the generic registerDriver()
and registerExchangeRateDriver() ship), so DriverRegistryProvider crashed
app boot on a clean composer install:
Call to undefined method InvoiceShelf\Modules\Registry::registerAiDriver()
Use registerDriver('ai', 'openrouter', ...) instead -- it stores under the
'ai' type exactly like the wrapper would, and AiConfigurationService /
AiDriverFactory read it back via allDrivers('ai') / driverMeta('ai', ...).
Verified by clean-reinstalling invoiceshelf/modules (no local patch) and
running `php artisan package:discover` -> boots clean.
* style: fix pre-existing Pint violations in backup services
BackupService.php and BackupConfigurationFactory.php (untouched by this
PR's boot fix) carried style violations from an earlier domain-reorg
refactor (6d1816bd). `pint --test` checks the whole tree and runs on any
PR that touches PHP, so these failed CI here. Auto-fixed with Pint
(braces_position, no_unused_imports, single_line_empty_body) so the check
goes green.
* build(deps): pull invoiceshelf/modules ^3.0.3 via VCS, restore registerAiDriver()
The 3.0.3 release adds Registry::registerAiDriver() (the method DriverRegistryProvider
and AiDriverFactoryTest call). Packagist has the package frozen, so resolve it directly
from the canonical GitHub repo via a composer VCS repository and require ^3.0.3 (the tag
exists; the freeze is Packagist-side only).
Now that the method ships, restore DriverRegistryProvider to Registry::registerAiDriver()
— reverting the temporary generic registerDriver('ai', ...) workaround — so it matches the
package's intended API and the existing tests. The provider is now net-identical to 3.x.
Verified: php artisan package:discover boots clean; the AI suite (incl. the previously
failing AiDriverFactoryTest) passes.
* test: provision modules_statuses.json in the test bootstrap
The Modules/HelloWorld integration test needs the module enabled at the nwidart
level, read from storage/app/modules_statuses.json at app boot. That file is
gitignored (created locally by `module:make`), so it's absent on CI and fresh
clones — HelloWorld stays disabled and the 5 integration tests fail with 404s.
Provision it (only if missing) in tests/Pest.php before any test boots the app,
so CI matches a local dev environment. Full suite: 462 pass.
* fix(test): enable HelloWorld via a committed modules_statuses.json
The Modules/HelloWorld integration test needs the module enabled at the nwidart
level — read from storage/app/modules_statuses.json by FileActivator. That file
is gitignored, so it's absent in CI / fresh clones, leaving HelloWorld disabled
and the 5 integration tests failing with 404s.
The previous tests/Pest.php provisioning (60a7f0d6) only worked under
`./vendor/bin/pest`. CI runs `php artisan test`, which boots the console app
first; FileActivator reads and caches the (absent) statuses at construction
BEFORE Pest.php runs, so test-runtime provisioning is too late. The file must
exist before any boot.
Commit the file via a storage/app/.gitignore negation, and revert the
ineffective Pest.php hack. Prod-safe: Modules/ is gitignored and not copied by
release.yaml, so a phantom "HelloWorld: true" status is ignored by nwidart (no
such module on disk). bootstrap/cache/modules.php is gitignored (absent in CI),
so nothing overrides the committed file.
Verified with `php artisan test --filter=HelloWorld` (the CI command) and the
full suite: 462 pass; pint clean.
* fix(test): commit the Modules/HelloWorld sample module
HelloWorldIntegrationTest exercises Modules/HelloWorld end-to-end, but Modules/
was gitignored (/Modules), so the module was absent from the repo and from CI —
the 5 integration tests 404'd, and the committed modules_statuses.json merely
enabled a module that wasn't there.
Track Modules/HelloWorld (the test fixture) via a `/Modules/*` + `!HelloWorld`
negation. Not shipped to prod (release.yaml omits Modules/). Now the module is
present, autoloaded (merge-plugin), and enabled (statuses file), so its provider
boots and the menu/settings/routes register.
* build: drop the boost:update post-update-cmd hook (breaks CI)
laravel/boost gates its commands to the local environment, so `php artisan
boost:update` fails in CI ("There are no commands defined in the boost
namespace"), making composer's post-update-cmd return exit 1.
It only began failing the build once Modules/HelloWorld/composer.json was
committed: the wikimedia merge-plugin then runs composer's update path on a
plain `composer install`, triggering post-update-cmd. Drop the auto-update
hook (run `boost:update` manually when needed); vendor:publish stays.
84 lines
3.2 KiB
JavaScript
Vendored
84 lines
3.2 KiB
JavaScript
Vendored
const { createBlock: e, createElementVNode: t, createTextVNode: n, createVNode: r, openBlock: i, ref: a, resolveComponent: o, toDisplayString: s, withCtx: c } = window.__invoiceshelf_vue;
|
|
//#region resources/js/pages/DashboardPage.vue
|
|
var l = { class: "p-6" }, u = { class: "flex items-center gap-3" }, d = { class: "text-xl font-semibold text-heading" }, f = { class: "mt-6 rounded-lg bg-surface-secondary p-4" }, p = { class: "space-y-1.5 text-sm text-muted" }, m = { class: "flex items-start gap-2" }, h = { class: "flex items-start gap-2" }, g = { class: "flex items-start gap-2" }, _ = {
|
|
__name: "DashboardPage",
|
|
setup(_) {
|
|
let v = a("Hello, world!");
|
|
return (a, _) => {
|
|
let y = o("BaseBreadcrumbItem"), b = o("BaseBreadcrumb"), x = o("BasePageHeader"), S = o("BaseIcon"), C = o("BaseCard"), w = o("BasePage");
|
|
return i(), e(w, null, {
|
|
default: c(() => [r(x, { title: "Hello World" }, {
|
|
default: c(() => [r(b, null, {
|
|
default: c(() => [r(y, {
|
|
title: "Home",
|
|
to: "dashboard"
|
|
}), r(y, {
|
|
title: "Hello World",
|
|
to: "#",
|
|
active: ""
|
|
})]),
|
|
_: 1
|
|
})]),
|
|
_: 1
|
|
}), r(C, { class: "mt-6" }, {
|
|
default: c(() => [t("div", l, [
|
|
t("div", u, [r(S, {
|
|
name: "HandRaisedIcon",
|
|
class: "h-8 w-8 text-primary-500"
|
|
}), t("h2", d, s(v.value), 1)]),
|
|
_[12] ||= t("p", { class: "mt-3 text-sm text-muted leading-relaxed" }, [
|
|
n(" This page is provided by the "),
|
|
t("strong", null, "HelloWorld"),
|
|
n(" module. It demonstrates how modules can ship their own Vue pages that render inside the InvoiceShelf SPA using globally registered Base components. ")
|
|
], -1),
|
|
t("div", f, [_[11] ||= t("h3", { class: "text-sm font-semibold text-heading mb-2" }, "How it works", -1), t("ul", p, [
|
|
t("li", m, [
|
|
r(S, {
|
|
name: "CheckIcon",
|
|
class: "h-4 w-4 text-green-500 shrink-0 mt-0.5"
|
|
}),
|
|
_[0] ||= n(" Module ships a compiled ", -1),
|
|
_[1] ||= t("code", { class: "text-primary-600" }, "init.js", -1),
|
|
_[2] ||= n(" that calls ", -1),
|
|
_[3] ||= t("code", { class: "text-primary-600" }, "window.InvoiceShelf.booting()", -1)
|
|
]),
|
|
t("li", h, [
|
|
r(S, {
|
|
name: "CheckIcon",
|
|
class: "h-4 w-4 text-green-500 shrink-0 mt-0.5"
|
|
}),
|
|
_[4] ||= n(" The callback receives ", -1),
|
|
_[5] ||= t("code", { class: "text-primary-600" }, "(app, router)", -1),
|
|
_[6] ||= n(" and adds routes via ", -1),
|
|
_[7] ||= t("code", { class: "text-primary-600" }, "router.addRoute()", -1)
|
|
]),
|
|
t("li", g, [
|
|
r(S, {
|
|
name: "CheckIcon",
|
|
class: "h-4 w-4 text-green-500 shrink-0 mt-0.5"
|
|
}),
|
|
_[8] ||= n(" Vue pages use globally registered ", -1),
|
|
_[9] ||= t("code", { class: "text-primary-600" }, "Base*", -1),
|
|
_[10] ||= n(" components — no imports needed ", -1)
|
|
])
|
|
])])
|
|
])]),
|
|
_: 1
|
|
})]),
|
|
_: 1
|
|
});
|
|
};
|
|
}
|
|
};
|
|
//#endregion
|
|
//#region resources/js/init.ts
|
|
window.InvoiceShelf.booting((e, t) => {
|
|
t.addRoute("admin", {
|
|
path: "modules/hello-world/dashboard",
|
|
name: "modules.hello-world.dashboard",
|
|
component: _,
|
|
meta: { requiresAuth: !0 }
|
|
});
|
|
});
|
|
//#endregion
|