Add comprehensive migration documentation for transitioning from the invalid Alpine.global() API to the correct Alpine.store() API. This guide addresses: - Critical issue: Alpine.global() does not exist in Alpine.js v3.15.8 - 26 TypeScript files requiring updates - Step-by-step migration instructions - Template syntax changes (namespace.function() → $store.namespace.function()) - Testing checklist and troubleshooting guide The migration will fix the "p.global is not a function" error currently breaking the theme switcher and all Alpine namespaces. Part 1 of 2 - covers TypeScript and template file updates.
12 KiB
Alpine.js Alpine.global() → Alpine.store() Migration Guide - Part 1
🔴 Critical Issue Identified
Problem: Your codebase uses Alpine.global() which DOES NOT EXIST in Alpine.js v3.15.8. This is causing the error:
Uncaught TypeError: p.global is not a function
📋 Root Cause Analysis
- Invalid API Usage:
Alpine.global()is not a valid Alpine.js v3 method - 26 Occurrences: Found across 26 TypeScript files
- Breaking Impact: Theme switcher and all Alpine namespaces are broken
✅ Solution Overview
Replace all Alpine.global() calls with Alpine.store(), the correct Alpine.js v3 API for registering global utilities.
Current Pattern (Broken):
Alpine.global("namespace", {
function1: () => { ... },
function2: () => { ... }
});
New Pattern (Correct):
Alpine.store("namespace", {
function1: () => { ... },
function2: () => { ... }
});
Template Usage Changes:
- Old:
@click="namespace.function()"→@click="$store.namespace.function()"
📁 Files Requiring Changes (26 TypeScript files)
Step 1: Update TypeScript Files
For each file, replace Alpine.global() with Alpine.store():
| File | Line | Namespace | Action |
|---|---|---|---|
admin.ts |
399 | admin |
Replace Alpine.global with Alpine.store |
api.ts |
102 | api |
Replace Alpine.global with Alpine.store |
api-explorer-docs.ts |
135 | apiExplorerDoc |
Replace Alpine.global with Alpine.store |
bookshelf.ts |
199 | bookshelf |
Replace Alpine.global with Alpine.store |
collection-rules.ts |
411 | collectionRules |
Replace Alpine.global with Alpine.store |
collections.ts |
917 | collections |
Replace Alpine.global with Alpine.store |
conflicts.ts |
219 | conflicts |
Replace Alpine.global with Alpine.store |
device-management.ts |
559 | devices |
Replace Alpine.global with Alpine.store |
docs.ts |
96, 103 | docs |
Replace Alpine.global with Alpine.store (2 occurrences) |
header.ts |
35 | header |
Replace Alpine.global with Alpine.store |
index.ts |
46 | index |
Replace Alpine.global with Alpine.store |
library.ts |
683 | library |
Replace Alpine.global with Alpine.store |
linking.ts |
204 | linking |
Replace Alpine.global with Alpine.store |
login.ts |
25 | login |
Replace Alpine.global with Alpine.store |
password_validation.ts |
192 | validation |
Replace Alpine.global with Alpine.store |
profile.ts |
44 | profile |
Replace Alpine.global with Alpine.store |
profile-modal.ts |
29 | profileModal |
Replace Alpine.global with Alpine.store |
queue.ts |
167 | queue |
Replace Alpine.global with Alpine.store |
register.ts |
14 | register |
Replace Alpine.global with Alpine.store |
search.ts |
310 | search |
Replace Alpine.global with Alpine.store |
themeDropdown.ts |
24 | themeDropdown |
Replace Alpine.global with Alpine.store |
toast.ts |
229 | showToast |
Replace Alpine.global with Alpine.store |
toast-error.ts |
33 | toastError |
Replace Alpine.global with Alpine.store |
unlinked_books.ts |
430 | unlinkedBooks |
Replace Alpine.global with Alpine.store |
woodPaneling.ts |
85 | woodPaneling |
Replace Alpine.global with Alpine.store |
Step 2: Update Template Files
For each .templ file that uses Alpine namespaces, update the syntax:
Old Syntax:
<div x-data="{}">
<button @click="namespace.function()">Click</button>
</div>
New Syntax:
<div x-data="{}">
<button @click="$store.namespace.function()">Click</button>
</div>
Templates Requiring Updates (to be identified by searching for namespace usage):
- All templates using
@click="admin." - All templates using
@click="api." - All templates using
@click="header." - All templates using
@click="showToast." - All templates using any other namespace from the list above
🔧 Detailed Step-by-Step Instructions
Phase 1: Update TypeScript Source Files
Step 1.1: Backup Current State
cd /home/nymusicman/Code/bookhoard
git add -A
git commit -m "Backup before Alpine.global() → Alpine.store() migration"
Step 1.2: Find All Alpine.global Occurrences
cd /home/nymusicman/Code/bookhoard/web/src
grep -rn "Alpine\.global" . | tee alpine-global-occurrences.txt
Expected output: 26 occurrences across 26 files
Step 1.3: Replace All Alpine.global with Alpine.store
Option A: Manual Replacement (Recommended for Understanding) For each file in the table above:
- Open the file
- Find the
Alpine.global()call - Replace
Alpine.globalwithAlpine.store - Save the file
Example (web/src/toast.ts:229):
// BEFORE (Line 229):
Alpine.global("showToast", {
error: (message: string, duration?: number) =>
showToast(message, "error", duration),
success: (message: string, duration?: number) =>
showToast(message, "success", duration),
info: (message: string, duration?: number) =>
showToast(message, "info", duration),
});
// AFTER (Line 229):
Alpine.store("showToast", {
error: (message: string, duration?: number) =>
showToast(message, "error", duration),
success: (message: string, duration?: number) =>
showToast(message, "success", duration),
info: (message: string, duration?: number) =>
showToast(message, "info", duration),
});
Option B: Automated Replacement (Faster)
cd /home/nymusicman/Code/bookhoard/web/src
find . -name "*.ts" -type f -exec sed -i 's/Alpine\.global(/Alpine.store(/g' {} \;
⚠️ Warning: Automated replacement will change all 26 occurrences at once. Verify with grep first:
grep -rn "Alpine\.global" . # Should return nothing after replacement
grep -rn "Alpine\.store" . # Should show all 26 occurrences
Step 1.4: Verify Changes
cd /home/nymusicman/Code/bookhoard/web/src
grep -c "Alpine\.store" *.ts | grep -v ":0"
Expected: Each of the 26 files should show 1 occurrence (except docs.ts which should show 2)
Step 1.5: Rebuild TypeScript
cd /home/nymusicman/Code/bookhoard/web
npm run build:ts
Expected output:
> bookhoard@1.0.0 build:ts
> cp node_modules/htmx.org/dist/htmx.min.js web/static/htmx.min.js && esbuild web/src/main.ts --bundle --outfile=web/static/main.js --sourcemap --target=es2020 --minify
web/static/main.js 167.9kb
web/static/main.js.map 538.7kb
⚡ Done in 18ms
Phase 2: Update Template Files
Step 2.1: Find All Namespace Usage in Templates
cd /home/nymusicman/Code/bookhoard/templates
grep -rn '@click="' .
This will show all click handlers that use namespaces. Look for patterns like:
@click="admin.deleteConfirm"@click="api.getUrl"@click="header.changeThemeTo"@click="showToast.error"- etc.
Step 2.2: Create Mapping Document
Create a text file with the old → new namespace mappings:
admin.function() → $store.admin.function()
api.function() → $store.api.function()
apiExplorerDoc.function() → $store.apiExplorerDoc.function()
bookshelf.function() → $store.bookshelf.function()
collectionRules.function() → $store.collectionRules.function()
collections.function() → $store.collections.function()
conflicts.function() → $store.conflicts.function()
devices.function() → $store.devices.function()
docs.function() → $store.docs.function()
header.function() → $store.header.function()
index.function() → $store.index.function()
library.function() → $store.library.function()
linking.function() → $store.linking.function()
login.function() → $store.login.function()
validation.function() → $store.validation.function()
profile.function() → $store.profile.function()
profileModal.function() → $store.profileModal.function()
queue.function() → $store.queue.function()
register.function() → $store.register.function()
search.function() → $store.search.function()
themeDropdown.function() → $store.themeDropdown.function()
showToast.function() → $store.showToast.function()
toastError.function() → $store.toastError.function()
unlinkedBooks.function() → $store.unlinkedBooks.function()
woodPaneling.function() → $store.woodPaneling.function()
Step 2.3: Update Templates (Iterative Approach)
For each namespace found in templates:
-
Search for all usages:
cd /home/nymusicman/Code/bookhoard/templates grep -rn 'namespace\.' . | grep "@click"Replace
namespacewith the actual namespace name (e.g.,admin,header, etc.) -
Replace in each file manually or using find/replace:
- Find:
@click="namespace.functionName" - Replace:
@click="$store.namespace.functionName"
- Find:
Example for header.templ:
Before:
@click="header.changeThemeTo('wood-light')"
@click="header.logout()"
After:
@click="$store.header.changeThemeTo('wood-light')"
@click="$store.header.logout()"
Step 2.4: Critical Template Priority
Update templates in this order (most critical first):
header.templ- Theme switcher (currently broken)index.templ- Main pagelibrary.templ- Core functionalitycollections.templ- Collection managementbookshelf.templ- Book displayapi_explorer.templ- API testingadmin.templ- Admin panelprofile.templ- User profilelogin.templ- Authenticationregister.templ- Registration- All other templates with namespace usage
Phase 3: Test the Migration
Step 3.1: Rebuild Container
cd /home/nymusicman/Code/bookhoard
docker-compose build
Step 3.2: Restart Container
docker-compose down
docker-compose up -d
Step 3.3: Verify Bundle
podman exec bookhoard grep -c "\.store(" /root/web/static/main.js
Expected: Should show all Alpine.store() calls (not Alpine.global())
Step 3.4: Test Theme Switcher (Critical)
- Open
http://localhost:8765in browser - Hard refresh:
Ctrl+Shift+R - Open browser console (F12)
- Click theme dropdown
- Select a theme
- Expected: Theme changes without error
- Expected Console:
Alpine.store('showToast') // Should return object, not undefined Alpine.store('header') // Should return object, not undefined
Step 3.5: Verify No Errors
Check browser console for:
- ✅ No
p.global is not a functionerrors - ✅ No
Uncaught TypeErrormessages - ✅ Alpine version shows:
3.15.8 - ✅ Stores are accessible via
$store
📊 Testing Checklist
After completing the migration, verify:
- No
Alpine.globalin any.tsfile - All 26
Alpine.storeregistrations present - Bundle size approximately 168KB
- Browser console shows no errors
- Theme switcher works correctly
- All dropdown menus open/close properly
- Toast notifications display correctly
- All forms submit without errors
- All click handlers work as expected
- Alpine directives (
x-show,@click, etc.) work correctly
🐛 Troubleshooting
Error: "Cannot read property 'function' of undefined"
Cause: Template still using old syntax namespace.function()
Fix: Change to $store.namespace.function()
Error: "Alpine.store is not a function"
Cause: TypeScript build didn't complete or using cached main.js
Fix: Run npm run build:ts and rebuild container
Error: "p.global is not a function" (still)
Cause: Some files still have Alpine.global()
Fix: Run grep -rn "Alpine\.global" web/src to find remaining occurrences
Theme switcher still broken
Cause: header.templ not updated with new syntax
Fix: Update all @click="header." to @click="$store.header."
📝 Next Steps (After This Guide)
Part 2 will cover:
- Advanced Alpine store patterns
- Reactive state management with stores
- Testing strategies for all templates
- Performance optimization
- Rollback plan if needed
🔗 References
Created: 2026-03-09
Alpine.js Version: 3.15.8
Status: Ready for Implementation