spine-framework 0.3.16 → 0.3.18
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/.framework/cli/commands/create-app.ts +1 -1
- package/.framework/cli/commands/dev.ts +215 -33
- package/.framework/cli/index.ts +37 -75
- package/.framework/functions/_shared/app-manifest.ts +8 -15
- package/.framework/functions/_shared/db.ts +11 -15
- package/.framework/functions/_shared/index.ts +7 -16
- package/.framework/functions/_shared/principal.ts +4 -62
- package/.framework/functions/_shared/resolve-ids.ts +6 -6
- package/.framework/functions/_shared/webhook-registry.ts +43 -1
- package/.framework/functions/admin-funnel.ts +104 -0
- package/.framework/functions/admin-install-funnel.ts +225 -0
- package/.framework/functions/admin-signals.ts +241 -0
- package/.framework/functions/integration-routes.ts +3 -7
- package/.framework/migrations/001_schema.sql +406 -0
- package/.framework/migrations/002_rls_and_functions.sql +710 -0
- package/.framework/migrations/003_system_data.sql +520 -0
- package/.framework/migrations/004_enhancements.sql +43 -0
- package/.framework/public/_redirects +3 -0
- package/.framework/public/spine-logo.jpg +0 -0
- package/.framework/public/spine-logo.svg +3 -0
- package/{scripts → .framework/scripts}/assemble-frontend.sh +8 -5
- package/{scripts → .framework/scripts}/assemble-functions.sh +4 -47
- package/{scripts → .framework/scripts}/assemble.sh +2 -8
- package/{scripts → .framework/scripts}/boundary-check.sh +5 -9
- package/{scripts → .framework/scripts}/check-core-integrity.sh +0 -0
- package/.framework/seeds/link_types/account_cli_instances.json +9 -0
- package/.framework/seeds/types/funnel_signal_use.json +98 -0
- package/.framework/seeds/types/spine_instance.json +109 -0
- package/.framework/src/App.tsx +11 -21
- package/.framework/src/components/CustomAppLoader.tsx +2 -19
- package/.framework/src/components/ui/accordion.tsx +1 -1
- package/.framework/src/components/ui/alert-dialog.tsx +1 -1
- package/.framework/src/components/ui/aspect-ratio.tsx +1 -1
- package/.framework/src/components/ui/avatar.tsx +1 -1
- package/.framework/src/components/ui/badge.tsx +2 -2
- package/.framework/src/components/ui/breadcrumb.tsx +2 -2
- package/.framework/src/components/ui/button-group.tsx +2 -2
- package/.framework/src/components/ui/button.tsx +2 -2
- package/.framework/src/components/ui/chart.tsx +6 -1
- package/.framework/src/components/ui/checkbox.tsx +1 -1
- package/.framework/src/components/ui/collapsible.tsx +1 -1
- package/.framework/src/components/ui/context-menu.tsx +1 -1
- package/.framework/src/components/ui/dialog.tsx +1 -1
- package/.framework/src/components/ui/direction.tsx +17 -1
- package/.framework/src/components/ui/dropdown-menu.tsx +1 -1
- package/.framework/src/components/ui/hover-card.tsx +1 -1
- package/.framework/src/components/ui/item.tsx +2 -2
- package/.framework/src/components/ui/label.tsx +1 -1
- package/.framework/src/components/ui/menubar.tsx +1 -1
- package/.framework/src/components/ui/navigation-menu.tsx +1 -1
- package/.framework/src/components/ui/popover.tsx +1 -1
- package/.framework/src/components/ui/progress.tsx +1 -1
- package/.framework/src/components/ui/radio-group.tsx +1 -1
- package/.framework/src/components/ui/scroll-area.tsx +1 -1
- package/.framework/src/components/ui/select.tsx +1 -1
- package/.framework/src/components/ui/separator.tsx +1 -1
- package/.framework/src/components/ui/sheet.tsx +1 -1
- package/.framework/src/components/ui/sidebar.tsx +6 -6
- package/.framework/src/components/ui/slider.tsx +1 -1
- package/.framework/src/components/ui/switch.tsx +1 -1
- package/.framework/src/components/ui/tabs.tsx +1 -1
- package/.framework/src/components/ui/toggle-group.tsx +1 -1
- package/.framework/src/components/ui/toggle.tsx +1 -1
- package/.framework/src/components/ui/tooltip.tsx +1 -1
- package/.framework/src/pages/auth/LoginPage.tsx +10 -9
- package/LICENSE.md +63 -93
- package/README.md +254 -129
- package/custom/.devin/skills/install-app/SKILL.md +39 -0
- package/custom/.devin/workflows/app-install.yaml +83 -0
- package/custom/README.md +79 -0
- package/docs/APPS.md +232 -0
- package/docs/ARCHITECTURE.md +246 -0
- package/docs/INSTALL.md +155 -0
- package/docs/README.md +170 -0
- package/docs/design-schema-spec.md +1837 -0
- package/docs/dev-guides/01-create-an-app.md +183 -0
- package/docs/dev-guides/02-create-a-function.md +178 -0
- package/docs/dev-guides/03-create-a-component.md +178 -0
- package/docs/dev-guides/04-webhook-handlers.md +129 -0
- package/docs/dev-guides/05-testing.md +168 -0
- package/docs/dev-guides/README.md +40 -0
- package/docs/npm-packages-plan.md +288 -0
- package/docs/spine-core--api-reference.md +822 -0
- package/package.json +78 -150
- package/.framework/cli/bin.cjs +0 -14
- package/.framework/cli/commands/claim.ts +0 -430
- package/.framework/cli/commands/init.ts +0 -219
- package/.framework/cli/commands/install-app.ts +0 -685
- package/.framework/cli/commands/migrate.ts +0 -178
- package/.framework/cli/commands/publish.ts +0 -191
- package/.framework/cli/commands/status.ts +0 -268
- package/.framework/cli/commands/uninstall-app.ts +0 -166
- package/.framework/cli/commands/update-app.ts +0 -397
- package/.framework/cli/welcome.cjs +0 -45
- package/.framework/config/signal-client.ts +0 -147
- package/.framework/config/signals.ts +0 -70
- package/.framework/docs/STABILITY.md +0 -52
- package/.framework/docs/examples/custom-app/README.md +0 -77
- package/.framework/docs/examples/custom-function/README.md +0 -27
- package/.framework/docs/examples/custom-function/handler.ts +0 -48
- package/.framework/docs/examples/custom-webhook/README.md +0 -68
- package/.framework/functions/handler-registry.ts +0 -22
- package/.framework/functions/signal.ts +0 -168
- package/.framework/migrations/000_foundation.sql +0 -1302
- package/.framework/migrations/001_seed.sql +0 -163
- package/.framework/migrations/002_seed_constraints.sql +0 -19
- package/.framework/migrations/003_auth_user_trigger.sql +0 -67
- package/.framework/migrations/004_app_version_tracking.sql +0 -8
- package/.framework/migrations/005_pipelines_slug_stages.sql +0 -21
- package/.framework/src/pages/auth/RegisterPage.tsx +0 -163
- package/CHANGELOG.md +0 -68
- package/STRUCTURE.md +0 -150
- package/bin/spine-framework.cjs +0 -62
- package/bin/welcome.cjs +0 -58
- package/bin/ws-shim.ts +0 -10
- package/config/components.json +0 -25
- package/config/deno.lock +0 -108
- package/config/package-lock.json +0 -17183
- package/config/postcss.config.cjs +0 -10
- package/config/tailwind.config.cjs +0 -78
- package/config/tsconfig.build.json +0 -32
- package/config/tsconfig.cli.json +0 -18
- package/config/tsconfig.json +0 -41
- package/config/tsconfig.node.json +0 -17
- package/config/tsconfig.node.tsbuildinfo +0 -1
- package/config/tsconfig.tsbuildinfo +0 -1
- package/config/typedoc.json +0 -16
- package/config/vite.config.d.ts +0 -2
- package/config/vite.config.ts +0 -71
- package/dist/cli/commands/agents.d.ts +0 -39
- package/dist/cli/commands/agents.d.ts.map +0 -1
- package/dist/cli/commands/auth.d.ts +0 -36
- package/dist/cli/commands/auth.d.ts.map +0 -1
- package/dist/cli/commands/claim.d.ts +0 -38
- package/dist/cli/commands/claim.d.ts.map +0 -1
- package/dist/cli/commands/create-app.d.ts +0 -23
- package/dist/cli/commands/create-app.d.ts.map +0 -1
- package/dist/cli/commands/dev.d.ts +0 -24
- package/dist/cli/commands/dev.d.ts.map +0 -1
- package/dist/cli/commands/doctor.d.ts +0 -42
- package/dist/cli/commands/doctor.d.ts.map +0 -1
- package/dist/cli/commands/generate.d.ts +0 -36
- package/dist/cli/commands/generate.d.ts.map +0 -1
- package/dist/cli/commands/init.d.ts +0 -20
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/install-app.d.ts +0 -30
- package/dist/cli/commands/install-app.d.ts.map +0 -1
- package/dist/cli/commands/items.d.ts +0 -45
- package/dist/cli/commands/items.d.ts.map +0 -1
- package/dist/cli/commands/migrate.d.ts +0 -21
- package/dist/cli/commands/migrate.d.ts.map +0 -1
- package/dist/cli/commands/migrations.d.ts +0 -41
- package/dist/cli/commands/migrations.d.ts.map +0 -1
- package/dist/cli/commands/pipelines.d.ts +0 -40
- package/dist/cli/commands/pipelines.d.ts.map +0 -1
- package/dist/cli/commands/publish.d.ts +0 -23
- package/dist/cli/commands/publish.d.ts.map +0 -1
- package/dist/cli/commands/status.d.ts +0 -23
- package/dist/cli/commands/status.d.ts.map +0 -1
- package/dist/cli/commands/system.d.ts +0 -29
- package/dist/cli/commands/system.d.ts.map +0 -1
- package/dist/cli/commands/test.d.ts +0 -46
- package/dist/cli/commands/test.d.ts.map +0 -1
- package/dist/cli/commands/uninstall-app.d.ts +0 -23
- package/dist/cli/commands/uninstall-app.d.ts.map +0 -1
- package/dist/cli/commands/update-app.d.ts +0 -24
- package/dist/cli/commands/update-app.d.ts.map +0 -1
- package/dist/cli/context.d.ts +0 -88
- package/dist/cli/context.d.ts.map +0 -1
- package/dist/cli/env-loader.d.ts +0 -14
- package/dist/cli/env-loader.d.ts.map +0 -1
- package/dist/cli/index.d.ts +0 -44
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/config/signals.d.ts +0 -82
- package/dist/config/signals.d.ts.map +0 -1
- package/dist/functions/_shared/agent-runner.d.ts +0 -156
- package/dist/functions/_shared/agent-runner.d.ts.map +0 -1
- package/dist/functions/_shared/app-manifest.d.ts +0 -68
- package/dist/functions/_shared/app-manifest.d.ts.map +0 -1
- package/dist/functions/_shared/audit.d.ts +0 -91
- package/dist/functions/_shared/audit.d.ts.map +0 -1
- package/dist/functions/_shared/db.d.ts +0 -125
- package/dist/functions/_shared/db.d.ts.map +0 -1
- package/dist/functions/_shared/index.d.ts +0 -299
- package/dist/functions/_shared/index.d.ts.map +0 -1
- package/dist/functions/_shared/middleware.d.ts +0 -315
- package/dist/functions/_shared/middleware.d.ts.map +0 -1
- package/dist/functions/_shared/permissions.d.ts +0 -626
- package/dist/functions/_shared/permissions.d.ts.map +0 -1
- package/dist/functions/_shared/pipeline-runner.d.ts +0 -124
- package/dist/functions/_shared/pipeline-runner.d.ts.map +0 -1
- package/dist/functions/_shared/principal.d.ts +0 -284
- package/dist/functions/_shared/principal.d.ts.map +0 -1
- package/dist/functions/_shared/resolve-ids.d.ts +0 -10
- package/dist/functions/_shared/resolve-ids.d.ts.map +0 -1
- package/dist/functions/_shared/schema-utils.d.ts +0 -181
- package/dist/functions/_shared/schema-utils.d.ts.map +0 -1
- package/dist/functions/_shared/testing.d.ts +0 -172
- package/dist/functions/_shared/testing.d.ts.map +0 -1
- package/dist/functions/_shared/trigger-engine.d.ts +0 -140
- package/dist/functions/_shared/trigger-engine.d.ts.map +0 -1
- package/dist/functions/_shared/webhook-registration.d.ts +0 -81
- package/dist/functions/_shared/webhook-registration.d.ts.map +0 -1
- package/dist/functions/_shared/webhook-registry.d.ts +0 -41
- package/dist/functions/_shared/webhook-registry.d.ts.map +0 -1
- package/dist/functions/account-nodes.d.ts +0 -48
- package/dist/functions/account-nodes.d.ts.map +0 -1
- package/dist/functions/admin-data.d.ts +0 -178
- package/dist/functions/admin-data.d.ts.map +0 -1
- package/dist/functions/ai-agents.d.ts +0 -125
- package/dist/functions/ai-agents.d.ts.map +0 -1
- package/dist/functions/api-keys.d.ts +0 -140
- package/dist/functions/api-keys.d.ts.map +0 -1
- package/dist/functions/apps.d.ts +0 -163
- package/dist/functions/apps.d.ts.map +0 -1
- package/dist/functions/auth.d.ts +0 -74
- package/dist/functions/auth.d.ts.map +0 -1
- package/dist/functions/debug-auth.d.ts +0 -33
- package/dist/functions/debug-auth.d.ts.map +0 -1
- package/dist/functions/embeddings.d.ts +0 -205
- package/dist/functions/embeddings.d.ts.map +0 -1
- package/dist/functions/handler-registry.d.ts +0 -22
- package/dist/functions/handler-registry.d.ts.map +0 -1
- package/dist/functions/integration-routes.d.ts +0 -45
- package/dist/functions/integration-routes.d.ts.map +0 -1
- package/dist/functions/integrations.d.ts +0 -124
- package/dist/functions/integrations.d.ts.map +0 -1
- package/dist/functions/item-progress.d.ts +0 -41
- package/dist/functions/item-progress.d.ts.map +0 -1
- package/dist/functions/logs.d.ts +0 -162
- package/dist/functions/logs.d.ts.map +0 -1
- package/dist/functions/observability.d.ts +0 -123
- package/dist/functions/observability.d.ts.map +0 -1
- package/dist/functions/pipeline-executions.d.ts +0 -190
- package/dist/functions/pipeline-executions.d.ts.map +0 -1
- package/dist/functions/pipelines.d.ts +0 -171
- package/dist/functions/pipelines.d.ts.map +0 -1
- package/dist/functions/prompt-configs.d.ts +0 -125
- package/dist/functions/prompt-configs.d.ts.map +0 -1
- package/dist/functions/roles.d.ts +0 -118
- package/dist/functions/roles.d.ts.map +0 -1
- package/dist/functions/signal.d.ts +0 -73
- package/dist/functions/signal.d.ts.map +0 -1
- package/dist/functions/system-cron.d.ts +0 -65
- package/dist/functions/system-cron.d.ts.map +0 -1
- package/dist/functions/system.d.ts +0 -29
- package/dist/functions/system.d.ts.map +0 -1
- package/dist/functions/tests.d.ts +0 -28
- package/dist/functions/tests.d.ts.map +0 -1
- package/dist/functions/timers.d.ts +0 -139
- package/dist/functions/timers.d.ts.map +0 -1
- package/dist/functions/triggers.d.ts +0 -203
- package/dist/functions/triggers.d.ts.map +0 -1
- package/dist/functions/types.d.ts +0 -151
- package/dist/functions/types.d.ts.map +0 -1
- package/dist/src/types/types.d.ts +0 -364
- package/dist/src/types/types.d.ts.map +0 -1
- package/index.html +0 -13
- package/netlify.toml +0 -36
- package/package-project.json +0 -71
- package/scripts/ingest-chunks.cjs +0 -202
- package/scripts/kb-chunk-parser.cjs +0 -312
- package/scripts/kb-chunk-parser.ts +0 -330
- package/scripts/load-test-app-install.ts +0 -484
- package/scripts/netlify-dev-wrapper.sh +0 -22
- package/vitest.config.ts +0 -45
- /package/{scripts → .framework/scripts}/app-install-cli.ts +0 -0
- /package/{scripts → .framework/scripts}/build-manifest.sh +0 -0
- /package/{scripts → .framework/scripts}/verify-integrity.sh +0 -0
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
set -euo pipefail
|
|
19
19
|
|
|
20
20
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
21
|
-
PROJECT_ROOT="$
|
|
21
|
+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
22
22
|
|
|
23
23
|
CORE_DIR="$PROJECT_ROOT/.framework/functions"
|
|
24
24
|
CUSTOM_DIR="$PROJECT_ROOT/custom"
|
|
@@ -42,23 +42,12 @@ fi
|
|
|
42
42
|
|
|
43
43
|
# 3. Overlay custom functions (overrides + additions), excluding test files
|
|
44
44
|
CUSTOM_COUNT=0
|
|
45
|
-
|
|
46
|
-
# 3a. Top-level custom/functions/ (project-level overrides)
|
|
47
45
|
if [ -d "$CUSTOM_DIR/functions" ]; then
|
|
46
|
+
# Copy all files except test files (*-test.ts, *.test.ts)
|
|
48
47
|
find "$CUSTOM_DIR/functions" -maxdepth 1 -name '*.ts' ! -name '*-test.ts' ! -name '*.test.ts' -exec cp {} "$TMP_DIR"/ \; 2>/dev/null || true
|
|
48
|
+
# Copy subdirectories if any
|
|
49
49
|
find "$CUSTOM_DIR/functions" -mindepth 1 -type d -exec sh -c 'dir="$1"; base=$(basename "$dir"); mkdir -p "'"$TMP_DIR"'/$base" && cp -r "$dir"/* "'"$TMP_DIR"'/$base/"' _ {} \; 2>/dev/null || true
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
# 3b. App functions from custom/apps/*/functions/ (installed app handlers)
|
|
53
|
-
for APP_FUNCTIONS_DIR in "$CUSTOM_DIR"/apps/*/functions; do
|
|
54
|
-
if [ -d "$APP_FUNCTIONS_DIR" ]; then
|
|
55
|
-
find "$APP_FUNCTIONS_DIR" -maxdepth 1 -name '*.ts' ! -name '*-test.ts' ! -name '*.test.ts' -exec cp {} "$TMP_DIR"/ \; 2>/dev/null || true
|
|
56
|
-
find "$APP_FUNCTIONS_DIR" -mindepth 1 -type d -exec sh -c 'dir="$1"; base=$(basename "$dir"); mkdir -p "'"$TMP_DIR"'/$base" && cp -r "$dir"/* "'"$TMP_DIR"'/$base/"' _ {} \; 2>/dev/null || true
|
|
57
|
-
fi
|
|
58
|
-
done
|
|
59
|
-
|
|
60
|
-
CUSTOM_COUNT=$(find "$CUSTOM_DIR" -path '*/functions/*.ts' ! -name '*-test.ts' ! -name '*.test.ts' 2>/dev/null | wc -l | tr -d ' ')
|
|
61
|
-
if [ "$CUSTOM_COUNT" -gt 0 ]; then
|
|
50
|
+
CUSTOM_COUNT=$(find "$CUSTOM_DIR/functions" -name '*.ts' ! -name '*-test.ts' ! -name '*.test.ts' 2>/dev/null | wc -l | tr -d ' ')
|
|
62
51
|
echo " ✓ Custom: $CUSTOM_COUNT files"
|
|
63
52
|
else
|
|
64
53
|
echo " ○ Custom: (empty)"
|
|
@@ -69,37 +58,5 @@ rm -rf "$TARGET_DIR"
|
|
|
69
58
|
mkdir -p "$(dirname "$TARGET_DIR")"
|
|
70
59
|
mv "$TMP_DIR" "$TARGET_DIR"
|
|
71
60
|
|
|
72
|
-
# 5. Generate handler-registry.ts — static imports of all custom_* handlers
|
|
73
|
-
# This replaces the stub in handler-registry.ts so esbuild can bundle all
|
|
74
|
-
# handlers into integration-routes at build time (no runtime dynamic imports).
|
|
75
|
-
REGISTRY_FILE="$TARGET_DIR/handler-registry.ts"
|
|
76
|
-
{
|
|
77
|
-
echo "// AUTO-GENERATED by assemble-functions.sh — do not edit manually"
|
|
78
|
-
echo "// Overrides the stub in .framework/functions/handler-registry.ts"
|
|
79
|
-
echo ""
|
|
80
|
-
|
|
81
|
-
# Collect all custom_*.ts handler files
|
|
82
|
-
HANDLER_NAMES=()
|
|
83
|
-
for f in "$TARGET_DIR"/custom_*.ts; do
|
|
84
|
-
[ -f "$f" ] || continue
|
|
85
|
-
name=$(basename "$f" .ts)
|
|
86
|
-
HANDLER_NAMES+=("$name")
|
|
87
|
-
var=$(echo "$name" | tr '-' '_')
|
|
88
|
-
echo "import * as ${var} from './${name}'"
|
|
89
|
-
done
|
|
90
|
-
|
|
91
|
-
echo ""
|
|
92
|
-
echo "export const HANDLER_REGISTRY: Record<string, any> = {"
|
|
93
|
-
|
|
94
|
-
for name in "${HANDLER_NAMES[@]}"; do
|
|
95
|
-
var=$(echo "$name" | tr '-' '_')
|
|
96
|
-
stripped="${name#custom_}"
|
|
97
|
-
echo " '${name}': ${var},"
|
|
98
|
-
echo " '${stripped}': ${var},"
|
|
99
|
-
done
|
|
100
|
-
|
|
101
|
-
echo "}"
|
|
102
|
-
} > "$REGISTRY_FILE"
|
|
103
|
-
|
|
104
61
|
echo " ✓ Assembled: $(find "$TARGET_DIR" -name '*.ts' ! -name '*-test.ts' ! -name '*.test.ts' | wc -l | tr -d ' ') total functions"
|
|
105
62
|
echo "✅ Done"
|
|
@@ -19,12 +19,6 @@ set -euo pipefail
|
|
|
19
19
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
20
20
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
21
21
|
|
|
22
|
-
# Detect if running inside node_modules (consumer project install)
|
|
23
|
-
# If so, output to actual project root (3 levels up from scripts/)
|
|
24
|
-
if [[ "$SCRIPT_DIR" == *"/node_modules/spine-framework/"* ]]; then
|
|
25
|
-
PROJECT_ROOT="$(dirname "$(dirname "$(dirname "$SCRIPT_DIR")")")"
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
22
|
echo "Assembling Spine..."
|
|
29
23
|
|
|
30
24
|
# Remove stale dist/ so Netlify CLI never reads its _redirects during dev
|
|
@@ -32,10 +26,10 @@ rm -rf "$PROJECT_ROOT/dist"
|
|
|
32
26
|
|
|
33
27
|
# Step 1: Assemble functions
|
|
34
28
|
echo "Assembling functions..."
|
|
35
|
-
|
|
29
|
+
bash "$SCRIPT_DIR/assemble-functions.sh"
|
|
36
30
|
|
|
37
31
|
# Step 2: Assemble frontend
|
|
38
32
|
echo "Assembling frontend..."
|
|
39
|
-
|
|
33
|
+
bash "$SCRIPT_DIR/assemble-frontend.sh"
|
|
40
34
|
|
|
41
35
|
echo "Spine assembly complete"
|
|
@@ -28,12 +28,8 @@ fi
|
|
|
28
28
|
echo ""
|
|
29
29
|
|
|
30
30
|
# Check 2: Core importing custom_ prefixed modules
|
|
31
|
-
# signal.ts is excluded: it uses a guarded dynamic import to optionally load a custom handler at runtime.
|
|
32
|
-
# handler-registry.ts is excluded: it's a core stub that gets generated at assembly time.
|
|
33
31
|
echo "2. Checking for custom_ module imports in core..."
|
|
34
|
-
if grep -r "from.*custom_\|import.*custom_" .framework/ --include="*.ts" --include="*.tsx" 2>/dev/null
|
|
35
|
-
| grep -v "signal\.ts:" \
|
|
36
|
-
| grep -v "handler-registry\.ts:"; then
|
|
32
|
+
if grep -r "from.*custom_\|import.*custom_" .framework/ --include="*.ts" --include="*.tsx" 2>/dev/null; then
|
|
37
33
|
echo " ❌ FAIL: Core files import custom_ modules"
|
|
38
34
|
VIOLATIONS=$((VIOLATIONS + 1))
|
|
39
35
|
else
|
|
@@ -76,13 +72,13 @@ else
|
|
|
76
72
|
fi
|
|
77
73
|
echo ""
|
|
78
74
|
|
|
79
|
-
# Check 5: Verify webhook registry
|
|
80
|
-
echo "5. Checking integration-routes uses registry
|
|
75
|
+
# Check 5: Verify webhook registry is used (not static imports)
|
|
76
|
+
echo "5. Checking integration-routes uses dynamic registry..."
|
|
81
77
|
if grep -q "webhookHandlers\|custom_webhook-handlers" .framework/functions/integration-routes.ts 2>/dev/null; then
|
|
82
|
-
echo " ❌ FAIL: integration-routes uses
|
|
78
|
+
echo " ❌ FAIL: integration-routes still uses static imports"
|
|
83
79
|
VIOLATIONS=$((VIOLATIONS + 1))
|
|
84
80
|
else
|
|
85
|
-
echo " ✅ PASS: integration-routes uses registry
|
|
81
|
+
echo " ✅ PASS: integration-routes uses dynamic registry"
|
|
86
82
|
fi
|
|
87
83
|
echo ""
|
|
88
84
|
|
|
File without changes
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "funnel_signal_use",
|
|
3
|
+
"kind": "item",
|
|
4
|
+
"name": "Usage Signal",
|
|
5
|
+
"description": "Tracks CLI and app usage signals from npm installations",
|
|
6
|
+
"design_schema": {
|
|
7
|
+
"fields": {
|
|
8
|
+
"title": {
|
|
9
|
+
"data_type": "text",
|
|
10
|
+
"label": "Title",
|
|
11
|
+
"required": true,
|
|
12
|
+
"system": true
|
|
13
|
+
},
|
|
14
|
+
"source": {
|
|
15
|
+
"data_type": "select",
|
|
16
|
+
"label": "Source",
|
|
17
|
+
"required": true,
|
|
18
|
+
"options": ["use"]
|
|
19
|
+
},
|
|
20
|
+
"stage": {
|
|
21
|
+
"data_type": "select",
|
|
22
|
+
"label": "Stage",
|
|
23
|
+
"required": true,
|
|
24
|
+
"options": ["installed", "claimed", "active"]
|
|
25
|
+
},
|
|
26
|
+
"action_type": {
|
|
27
|
+
"data_type": "text",
|
|
28
|
+
"label": "Action Type",
|
|
29
|
+
"required": true
|
|
30
|
+
},
|
|
31
|
+
"action_value": {
|
|
32
|
+
"data_type": "number",
|
|
33
|
+
"label": "Action Value",
|
|
34
|
+
"required": true
|
|
35
|
+
},
|
|
36
|
+
"serial": {
|
|
37
|
+
"data_type": "text",
|
|
38
|
+
"label": "Install Serial",
|
|
39
|
+
"required": true
|
|
40
|
+
},
|
|
41
|
+
"app_slug": {
|
|
42
|
+
"data_type": "select",
|
|
43
|
+
"label": "App",
|
|
44
|
+
"required": false,
|
|
45
|
+
"options": ["framework", "cortex", "portal"]
|
|
46
|
+
},
|
|
47
|
+
"app_version": {
|
|
48
|
+
"data_type": "text",
|
|
49
|
+
"label": "App Version",
|
|
50
|
+
"required": false
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"views": {
|
|
54
|
+
"default_list": {
|
|
55
|
+
"type": "list",
|
|
56
|
+
"display": "table",
|
|
57
|
+
"label": "Usage Signals",
|
|
58
|
+
"fields": {
|
|
59
|
+
"title": { "sortable": true, "display_type": "text" },
|
|
60
|
+
"action_type": { "sortable": true, "display_type": "badge" },
|
|
61
|
+
"stage": { "sortable": true, "display_type": "badge" },
|
|
62
|
+
"serial": { "sortable": true, "display_type": "text" },
|
|
63
|
+
"created_at": { "sortable": true, "display_type": "timestamp" }
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"default_detail": {
|
|
67
|
+
"type": "detail",
|
|
68
|
+
"label": "Signal Detail",
|
|
69
|
+
"sections": [
|
|
70
|
+
{
|
|
71
|
+
"title": "Signal",
|
|
72
|
+
"fields": {
|
|
73
|
+
"action_type": { "display_type": "input" },
|
|
74
|
+
"action_value": { "display_type": "input" },
|
|
75
|
+
"stage": { "display_type": "select" }
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"title": "Instance",
|
|
80
|
+
"fields": {
|
|
81
|
+
"serial": { "display_type": "input" },
|
|
82
|
+
"app_slug": { "display_type": "select" },
|
|
83
|
+
"app_version": { "display_type": "input" }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"record_permissions": {
|
|
90
|
+
"system-admin": ["create", "read", "update", "delete"],
|
|
91
|
+
"support": ["create", "read", "update"],
|
|
92
|
+
"member": ["create", "read"]
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"validation_schema": {},
|
|
96
|
+
"ownership": "pack",
|
|
97
|
+
"is_active": true
|
|
98
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "spine_instance",
|
|
3
|
+
"kind": "item",
|
|
4
|
+
"name": "CLI Instance",
|
|
5
|
+
"description": "Tracks npm package installations per device",
|
|
6
|
+
"design_schema": {
|
|
7
|
+
"fields": {
|
|
8
|
+
"title": {
|
|
9
|
+
"data_type": "text",
|
|
10
|
+
"label": "Title",
|
|
11
|
+
"required": true,
|
|
12
|
+
"system": true
|
|
13
|
+
},
|
|
14
|
+
"serial": {
|
|
15
|
+
"data_type": "text",
|
|
16
|
+
"label": "Install Serial",
|
|
17
|
+
"required": true,
|
|
18
|
+
"validation": {
|
|
19
|
+
"pattern": "^sf_inst_[a-z0-9-]+$"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"app_slug": {
|
|
23
|
+
"data_type": "select",
|
|
24
|
+
"label": "App",
|
|
25
|
+
"required": true,
|
|
26
|
+
"options": ["framework", "cortex", "portal"]
|
|
27
|
+
},
|
|
28
|
+
"version": {
|
|
29
|
+
"data_type": "text",
|
|
30
|
+
"label": "Version",
|
|
31
|
+
"required": true
|
|
32
|
+
},
|
|
33
|
+
"claimed_by_person_id": {
|
|
34
|
+
"data_type": "reference",
|
|
35
|
+
"label": "Claimed By",
|
|
36
|
+
"required": false,
|
|
37
|
+
"validation": {
|
|
38
|
+
"reference_kind": "person"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"claimed_at": {
|
|
42
|
+
"data_type": "datetime",
|
|
43
|
+
"label": "Claimed At",
|
|
44
|
+
"required": false
|
|
45
|
+
},
|
|
46
|
+
"first_seen_at": {
|
|
47
|
+
"data_type": "datetime",
|
|
48
|
+
"label": "First Seen",
|
|
49
|
+
"required": true
|
|
50
|
+
},
|
|
51
|
+
"last_signal_at": {
|
|
52
|
+
"data_type": "datetime",
|
|
53
|
+
"label": "Last Signal",
|
|
54
|
+
"required": false
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"views": {
|
|
58
|
+
"default_list": {
|
|
59
|
+
"type": "list",
|
|
60
|
+
"display": "table",
|
|
61
|
+
"label": "CLI Instances",
|
|
62
|
+
"fields": {
|
|
63
|
+
"title": { "sortable": true, "display_type": "text" },
|
|
64
|
+
"app_slug": { "sortable": true, "display_type": "badge" },
|
|
65
|
+
"version": { "sortable": true, "display_type": "text" },
|
|
66
|
+
"claimed_at": { "sortable": true, "display_type": "timestamp" },
|
|
67
|
+
"last_signal_at": { "sortable": true, "display_type": "timestamp" }
|
|
68
|
+
},
|
|
69
|
+
"default_sort": { "field": "created_at", "direction": "desc" }
|
|
70
|
+
},
|
|
71
|
+
"default_detail": {
|
|
72
|
+
"type": "detail",
|
|
73
|
+
"label": "Instance Detail",
|
|
74
|
+
"sections": [
|
|
75
|
+
{
|
|
76
|
+
"title": "Instance",
|
|
77
|
+
"fields": {
|
|
78
|
+
"serial": { "display_type": "input" },
|
|
79
|
+
"app_slug": { "display_type": "select" },
|
|
80
|
+
"version": { "display_type": "input" }
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"title": "Claim",
|
|
85
|
+
"fields": {
|
|
86
|
+
"claimed_by_person_id": { "display_type": "reference_picker" },
|
|
87
|
+
"claimed_at": { "display_type": "timestamp" }
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"title": "Activity",
|
|
92
|
+
"fields": {
|
|
93
|
+
"first_seen_at": { "display_type": "timestamp" },
|
|
94
|
+
"last_signal_at": { "display_type": "timestamp" }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"record_permissions": {
|
|
101
|
+
"system-admin": ["create", "read", "update", "delete"],
|
|
102
|
+
"support": ["create", "read", "update"],
|
|
103
|
+
"member": ["create", "read", "update"]
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"validation_schema": {},
|
|
107
|
+
"ownership": "pack",
|
|
108
|
+
"is_active": true
|
|
109
|
+
}
|
package/.framework/src/App.tsx
CHANGED
|
@@ -3,12 +3,11 @@ import { Routes, Route, Navigate } from 'react-router-dom'
|
|
|
3
3
|
import { useAuth } from './contexts/AuthContext'
|
|
4
4
|
import { LoadingSpinner } from './components/ui/LoadingSpinner'
|
|
5
5
|
import { LoginPage } from './pages/auth/LoginPage'
|
|
6
|
-
import { RegisterPage } from './pages/auth/RegisterPage'
|
|
7
6
|
import { NotFoundPage } from './pages/NotFoundPage'
|
|
8
7
|
import { DashboardPage } from './pages/DashboardPage'
|
|
9
8
|
import { AppWrapper } from './components/AppWrapper'
|
|
10
9
|
import { AppsRegistryProvider, useAppsRegistry } from './contexts/AppContext'
|
|
11
|
-
import { CustomAppLoader
|
|
10
|
+
import { CustomAppLoader } from './components/CustomAppLoader'
|
|
12
11
|
import { GenericAppShell } from './components/app-shell/GenericAppShell'
|
|
13
12
|
import { APIPage } from './pages/spine-framework/APIPage'
|
|
14
13
|
import { CLIPage } from './pages/spine-framework/CLIPage'
|
|
@@ -34,7 +33,6 @@ function App() {
|
|
|
34
33
|
{!user ? (
|
|
35
34
|
<Routes>
|
|
36
35
|
<Route path="/login" element={<LoginPage />} />
|
|
37
|
-
<Route path="/register" element={<RegisterPage />} />
|
|
38
36
|
<Route path="*" element={<Navigate to="/login" replace />} />
|
|
39
37
|
</Routes>
|
|
40
38
|
) : (
|
|
@@ -58,31 +56,26 @@ function AuthenticatedRouter() {
|
|
|
58
56
|
)
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
// Filter to apps that are physically present in this build (custom renderer only —
|
|
62
|
-
// generic apps have no module to load so they're always allowed through).
|
|
63
|
-
const installedSlugs = getInstalledAppSlugs()
|
|
64
|
-
|
|
65
59
|
// Sort: explicit prefixes first, root (/) last
|
|
66
60
|
const sorted = [...apps]
|
|
67
61
|
.filter(app => app.slug !== 'spine-framework' && !app.route_prefix?.startsWith('/spine-framework'))
|
|
68
|
-
.filter(app => app.renderer !== 'custom' || installedSlugs.has(app.slug))
|
|
69
62
|
.sort((a, b) => {
|
|
70
63
|
if (a.route_prefix === '/') return 1
|
|
71
64
|
if (b.route_prefix === '/') return -1
|
|
72
65
|
return (b.route_prefix?.length || 0) - (a.route_prefix?.length || 0)
|
|
73
66
|
})
|
|
74
67
|
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
const
|
|
68
|
+
// Determine default redirect: first app with a route_prefix, or fall back to dashboard
|
|
69
|
+
const defaultApp = sorted.find(app => app.route_prefix && app.route_prefix !== '/')
|
|
70
|
+
const defaultRedirect = defaultApp?.route_prefix || '/dashboard'
|
|
78
71
|
|
|
79
72
|
return (
|
|
80
73
|
<Suspense fallback={<div className="min-h-screen flex items-center justify-center"><LoadingSpinner /></div>}>
|
|
81
74
|
<Routes>
|
|
82
|
-
{/* Default redirect
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
{/* Default redirect to first available app, or dashboard if no apps */}
|
|
76
|
+
<Route path="/" element={<Navigate to={defaultRedirect} replace />} />
|
|
77
|
+
<Route path="/dashboard" element={<DashboardPage />} />
|
|
78
|
+
|
|
86
79
|
{/* Login route for authenticated users (redirects to qualified app) */}
|
|
87
80
|
<Route path="/login" element={<LoginPage />} />
|
|
88
81
|
|
|
@@ -94,14 +87,12 @@ function AuthenticatedRouter() {
|
|
|
94
87
|
{/* Dynamic app routes */}
|
|
95
88
|
{sorted.map(app => {
|
|
96
89
|
const prefix = app.route_prefix!
|
|
97
|
-
// React Router v6: path="/*" does NOT work for root — must use path="*"
|
|
98
|
-
const routePath = prefix === '/' ? '*' : `${prefix}/*`
|
|
99
90
|
|
|
100
91
|
if (app.renderer === 'custom') {
|
|
101
92
|
return (
|
|
102
93
|
<Route
|
|
103
94
|
key={app.slug}
|
|
104
|
-
path={
|
|
95
|
+
path={`${prefix}/*`}
|
|
105
96
|
element={
|
|
106
97
|
<AppWrapper app={app}>
|
|
107
98
|
<CustomAppLoader slug={app.slug} />
|
|
@@ -115,7 +106,7 @@ function AuthenticatedRouter() {
|
|
|
115
106
|
return (
|
|
116
107
|
<Route
|
|
117
108
|
key={app.slug}
|
|
118
|
-
path={
|
|
109
|
+
path={`${prefix}/*`}
|
|
119
110
|
element={
|
|
120
111
|
<AppWrapper app={app}>
|
|
121
112
|
<GenericAppShell app={app} />
|
|
@@ -128,8 +119,7 @@ function AuthenticatedRouter() {
|
|
|
128
119
|
return null
|
|
129
120
|
})}
|
|
130
121
|
|
|
131
|
-
|
|
132
|
-
{!hasRootApp && <Route path="*" element={<NotFoundPage />} />}
|
|
122
|
+
<Route path="*" element={<NotFoundPage />} />
|
|
133
123
|
</Routes>
|
|
134
124
|
</Suspense>
|
|
135
125
|
)
|
|
@@ -57,33 +57,16 @@ class AppErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState>
|
|
|
57
57
|
// Static glob maps — Vite analyzes these at build time and builds a complete
|
|
58
58
|
// module map. Runtime lookup is just a map key lookup, no dynamic string eval.
|
|
59
59
|
// Custom apps take precedence over core apps with the same slug.
|
|
60
|
-
const customAppModules = import.meta.glob('
|
|
60
|
+
const customAppModules = import.meta.glob('../../../custom/apps/*/index.tsx')
|
|
61
61
|
const coreAppModules = import.meta.glob('../apps/*/index.tsx')
|
|
62
62
|
|
|
63
|
-
// Extract app slug from glob key path (e.g., '.../apps/xyz/index.tsx' → 'xyz')
|
|
64
|
-
function slugFromKey(key: string): string {
|
|
65
|
-
return key.split('/').slice(-2)[0]
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Returns the set of app slugs that are physically present in this build.
|
|
70
|
-
* Used by App.tsx to filter DB app records down to only what's actually installed,
|
|
71
|
-
* preventing route registration for apps that exist in the DB but not this deployment.
|
|
72
|
-
*/
|
|
73
|
-
export function getInstalledAppSlugs(): Set<string> {
|
|
74
|
-
const slugs = new Set<string>()
|
|
75
|
-
Object.keys(customAppModules).forEach(k => slugs.add(slugFromKey(k)))
|
|
76
|
-
Object.keys(coreAppModules).forEach(k => slugs.add(slugFromKey(k)))
|
|
77
|
-
return slugs
|
|
78
|
-
}
|
|
79
|
-
|
|
80
63
|
// Module-level cache for lazy components to avoid re-creating on each render
|
|
81
64
|
const appModuleCache = new Map<string, React.LazyExoticComponent<React.ComponentType>>()
|
|
82
65
|
|
|
83
66
|
// Resolve the glob key for a given slug from the custom or core map.
|
|
84
67
|
function resolveAppLoader(slug: string): (() => Promise<{ default: React.ComponentType }>) | null {
|
|
85
68
|
// Check custom first (custom/apps/{slug}/index.tsx)
|
|
86
|
-
const customKey =
|
|
69
|
+
const customKey = `../../../custom/apps/${slug}/index.tsx`
|
|
87
70
|
if (customAppModules[customKey]) {
|
|
88
71
|
return customAppModules[customKey] as () => Promise<{ default: React.ComponentType }>
|
|
89
72
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
-
import { Slot } from "
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
4
|
|
|
5
5
|
import { cn } from "@/lib/utils"
|
|
6
6
|
|
|
@@ -34,7 +34,7 @@ function Badge({
|
|
|
34
34
|
...props
|
|
35
35
|
}: React.ComponentProps<"span"> &
|
|
36
36
|
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
|
37
|
-
const Comp = asChild ? Slot : "span"
|
|
37
|
+
const Comp = asChild ? Slot.Root : "span"
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
40
|
<Comp
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
-
import { Slot } from "
|
|
2
|
+
import { Slot } from "radix-ui"
|
|
3
3
|
|
|
4
4
|
import { cn } from "@/lib/utils"
|
|
5
5
|
import { ChevronRightIcon, MoreHorizontalIcon } from "lucide-react"
|
|
@@ -45,7 +45,7 @@ function BreadcrumbLink({
|
|
|
45
45
|
}: React.ComponentProps<"a"> & {
|
|
46
46
|
asChild?: boolean
|
|
47
47
|
}) {
|
|
48
|
-
const Comp = asChild ? Slot : "a"
|
|
48
|
+
const Comp = asChild ? Slot.Root : "a"
|
|
49
49
|
|
|
50
50
|
return (
|
|
51
51
|
<Comp
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
-
import { Slot } from "
|
|
2
|
+
import { Slot } from "radix-ui"
|
|
3
3
|
|
|
4
4
|
import { cn } from "@/lib/utils"
|
|
5
5
|
import { Separator } from "@/components/ui/separator"
|
|
@@ -44,7 +44,7 @@ function ButtonGroupText({
|
|
|
44
44
|
}: React.ComponentProps<"div"> & {
|
|
45
45
|
asChild?: boolean
|
|
46
46
|
}) {
|
|
47
|
-
const Comp = asChild ? Slot : "div"
|
|
47
|
+
const Comp = asChild ? Slot.Root : "div"
|
|
48
48
|
|
|
49
49
|
return (
|
|
50
50
|
<Comp
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
-
import { Slot } from "
|
|
3
|
+
import { Slot } from "radix-ui"
|
|
4
4
|
|
|
5
5
|
import { cn } from "@/lib/utils"
|
|
6
6
|
|
|
@@ -49,7 +49,7 @@ function Button({
|
|
|
49
49
|
VariantProps<typeof buttonVariants> & {
|
|
50
50
|
asChild?: boolean
|
|
51
51
|
}) {
|
|
52
|
-
const Comp = asChild ? Slot : "button"
|
|
52
|
+
const Comp = asChild ? Slot.Root : "button"
|
|
53
53
|
|
|
54
54
|
return (
|
|
55
55
|
<Comp
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import * as RechartsPrimitive from "recharts"
|
|
5
|
+
import type { TooltipValueType } from "recharts"
|
|
5
6
|
|
|
6
7
|
import { cn } from "@/lib/utils"
|
|
7
8
|
|
|
@@ -9,6 +10,7 @@ import { cn } from "@/lib/utils"
|
|
|
9
10
|
const THEMES = { light: "", dark: ".dark" } as const
|
|
10
11
|
|
|
11
12
|
const INITIAL_DIMENSION = { width: 320, height: 200 } as const
|
|
13
|
+
type TooltipNameType = number | string
|
|
12
14
|
|
|
13
15
|
export type ChartConfig = Record<
|
|
14
16
|
string,
|
|
@@ -136,7 +138,10 @@ function ChartTooltipContent({
|
|
|
136
138
|
nameKey?: string
|
|
137
139
|
labelKey?: string
|
|
138
140
|
} & Omit<
|
|
139
|
-
RechartsPrimitive.
|
|
141
|
+
RechartsPrimitive.DefaultTooltipContentProps<
|
|
142
|
+
TooltipValueType,
|
|
143
|
+
TooltipNameType
|
|
144
|
+
>,
|
|
140
145
|
"accessibilityLayer"
|
|
141
146
|
>) {
|
|
142
147
|
const { config } = useChart()
|