@olonjs/cli 3.0.149 → 3.0.150

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.
@@ -1817,11 +1817,14 @@ cat << 'END_OF_FILE_CONTENT' > "package.json"
1817
1817
  "@tiptap/extension-link": "^2.11.5",
1818
1818
  "@tiptap/react": "^2.11.5",
1819
1819
  "@tiptap/starter-kit": "^2.11.5",
1820
- "@olonjs/core": "^1.1.16",
1820
+ "@olonjs/core": "^1.1.17",
1821
+ "@olonjs/react": "^0.1.0",
1822
+ "@olonjs/studio": "^0.1.0",
1821
1823
  "class-variance-authority": "^0.7.1",
1822
1824
  "clsx": "^2.1.1",
1823
1825
  "lucide-react": "^0.474.0",
1824
1826
  "motion": "^12.23.24",
1827
+ "radix-ui": "^1.4.3",
1825
1828
  "react": "^19.0.0",
1826
1829
  "react-markdown": "^9.0.1",
1827
1830
  "react-dom": "^19.0.0",
@@ -2191,8 +2194,6 @@ async function readJsonFile(filePath) {
2191
2194
  }
2192
2195
 
2193
2196
  async function expandCollectionTarget(slug, pageFilePath) {
2194
- if (!/\[[^\]]+\]/.test(slug)) return [slug];
2195
-
2196
2197
  let pageConfig;
2197
2198
  try {
2198
2199
  pageConfig = await readJsonFile(pageFilePath);
@@ -2206,7 +2207,14 @@ async function expandCollectionTarget(slug, pageFilePath) {
2206
2207
  }
2207
2208
 
2208
2209
  const token = `[${binding.paramKey}]`;
2209
- if (!slug.includes(token)) return [slug];
2210
+ // Prefer authored route pattern (page.slug) when the file path is not parametric.
2211
+ const authoredSlug =
2212
+ typeof pageConfig.slug === 'string'
2213
+ ? pageConfig.slug.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '')
2214
+ : '';
2215
+ const routePattern =
2216
+ authoredSlug.includes(token) ? authoredSlug : slug.includes(token) ? slug : '';
2217
+ if (!routePattern) return [slug];
2210
2218
 
2211
2219
  const collectionPath = path.resolve(collectionsDir, binding.source, `${binding.source}.json`);
2212
2220
  let collection;
@@ -2218,7 +2226,9 @@ async function expandCollectionTarget(slug, pageFilePath) {
2218
2226
 
2219
2227
  if (!collection || typeof collection !== 'object' || Array.isArray(collection)) return [slug];
2220
2228
  const itemIds = Object.keys(collection).sort((a, b) => a.localeCompare(b));
2221
- return itemIds.length > 0 ? itemIds.map((itemId) => slug.replace(token, itemId)) : [slug];
2229
+ return itemIds.length > 0
2230
+ ? itemIds.map((itemId) => routePattern.replace(token, itemId))
2231
+ : [slug];
2222
2232
  }
2223
2233
 
2224
2234
  async function listJsonFilesRecursive(dir) {
@@ -2942,10 +2952,9 @@ cat << 'END_OF_FILE_CONTENT' > "src/App.tsx"
2942
2952
  * Bootstrap, persistence, and engine wiring — logic lives in lib/hooks.
2943
2953
  */
2944
2954
  import { useEffect, useMemo } from 'react';
2945
- import { JsonPagesEngine } from '@olonjs/core';
2955
+ import { JsonPagesEngine, OlonFormsContext } from '@olonjs/react';
2946
2956
  import type { JsonPagesConfig, ProjectState } from '@olonjs/core';
2947
2957
  import { withBasePath } from '@olonjs/core';
2948
- import { OlonFormsContext } from '@olonjs/core';
2949
2958
  import { ComponentRegistry } from '@/lib/ComponentRegistry';
2950
2959
  import { CollectionRegistry } from '@/lib/CollectionRegistry';
2951
2960
  import { SECTION_SCHEMAS } from '@/lib/schemas';
@@ -4077,7 +4086,7 @@ END_OF_FILE_CONTENT
4077
4086
  echo "Creating src/components/form-demo/View.tsx..."
4078
4087
  cat << 'END_OF_FILE_CONTENT' > "src/components/form-demo/View.tsx"
4079
4088
  import { Icon } from '@/lib/IconResolver';
4080
- import { useFormState } from '@olonjs/core';
4089
+ import { useFormState } from '@olonjs/react';
4081
4090
  import type { FormDemoData } from './types';
4082
4091
 
4083
4092
  type FormDemoViewProps = {
@@ -5622,7 +5631,8 @@ import {
5622
5631
  Code2, Quote, SquareCode,
5623
5632
  Link2, Unlink2, ImagePlus, Eraser,
5624
5633
  } from 'lucide-react';
5625
- import { STUDIO_EVENTS, useConfig, useStudio } from '@olonjs/core';
5634
+ import { STUDIO_EVENTS } from '@olonjs/core';
5635
+ import { useConfig, useStudio } from '@olonjs/react';
5626
5636
  import type { TiptapData, TiptapSettings } from './types';
5627
5637
 
5628
5638
  // ── UI primitives ─────────────────────────────────────────────────
@@ -8582,7 +8592,7 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/collections/libri/libri.json"
8582
8592
  "id": "1984",
8583
8593
  "title": "1984",
8584
8594
  "author": {
8585
- "$ref": "../autori/autori.json#/alessandro-baricco"
8595
+ "$ref": "../autori/autori.json#/george-orwell"
8586
8596
  },
8587
8597
  "year": 1949,
8588
8598
  "genre": "Distopia",
@@ -9686,14 +9696,8 @@ echo "Creating src/entry-ssg.tsx..."
9686
9696
  cat << 'END_OF_FILE_CONTENT' > "src/entry-ssg.tsx"
9687
9697
  import { renderToString } from 'react-dom/server';
9688
9698
  import { StaticRouter } from 'react-router-dom/server';
9689
- import {
9690
- ConfigProvider,
9691
- PageRenderer,
9692
- StudioProvider,
9693
- contract,
9694
- resolvePageMatchFromRegistry,
9695
- resolveRuntimeConfig,
9696
- } from '@olonjs/core';
9699
+ import { ConfigProvider, PageRenderer, StudioProvider } from '@olonjs/react';
9700
+ import { contract, resolvePageMatchFromRegistry, resolveRuntimeConfig } from '@olonjs/core';
9697
9701
  import type { JsonPagesConfig, PageConfig, SiteConfig, ThemeConfig } from '@/types';
9698
9702
  import { ThemeProvider } from '@/components/ThemeProvider';
9699
9703
  import { ComponentRegistry } from '@/lib/ComponentRegistry';
@@ -11445,7 +11449,6 @@ export function coerceSiteConfig(value: unknown): SiteConfig | null {
11445
11449
  }
11446
11450
  if (!isObjectRecord(input)) return null;
11447
11451
  if (!isObjectRecord(input.identity)) return null;
11448
- if (!Array.isArray(input.pages)) return null;
11449
11452
 
11450
11453
  return input as unknown as SiteConfig;
11451
11454
  }
@@ -11712,7 +11715,6 @@ export function getHydratedData(
11712
11715
  }
11713
11716
 
11714
11717
  END_OF_FILE_CONTENT
11715
- mkdir -p "src/lib/editorial"
11716
11718
  echo "Creating src/lib/getFileCollections.ts..."
11717
11719
  cat << 'END_OF_FILE_CONTENT' > "src/lib/getFileCollections.ts"
11718
11720
  import type { JsonPagesConfig } from '@/types';
@@ -12940,8 +12942,9 @@ function isRemoteStylesheetHref(value: string): boolean {
12940
12942
  export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string[]; rest: string } {
12941
12943
  const hrefs = new Set<string>();
12942
12944
  const leadingTriviaPattern = /^(?:\s+|\/\*[\s\S]*?\*\/)*/;
12945
+ // Vite/Tailwind may emit `@import url("...")` or compacted `@import"https://..."`.
12943
12946
  const importPattern =
12944
- /^@import\s+url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)\s*([^;]*);/i;
12947
+ /^@import(?:\s*url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)|\s*(['"])([^'"]+)\4)\s*([^;]*);/i;
12945
12948
  let rest = cssText;
12946
12949
 
12947
12950
  for (;;) {
@@ -12953,8 +12956,8 @@ export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string
12953
12956
  const match = rest.match(importPattern);
12954
12957
  if (!match) break;
12955
12958
 
12956
- const href = (match[1] ?? match[2] ?? match[3] ?? '').trim();
12957
- const trailingDirectives = (match[4] ?? '').trim();
12959
+ const href = (match[1] ?? match[2] ?? match[3] ?? match[5] ?? '').trim();
12960
+ const trailingDirectives = (match[6] ?? '').trim();
12958
12961
 
12959
12962
  if (!isRemoteStylesheetHref(href) || trailingDirectives.length > 0) {
12960
12963
  break;
@@ -13484,7 +13487,7 @@ END_OF_FILE_CONTENT
13484
13487
  echo "Creating src/lib/useOlonForms.ts..."
13485
13488
  cat << 'END_OF_FILE_CONTENT' > "src/lib/useOlonForms.ts"
13486
13489
  import { useCallback, useEffect, useState } from 'react';
13487
- import type { FormState } from '@olonjs/core';
13490
+ import type { FormState } from '@olonjs/react';
13488
13491
 
13489
13492
  const API_BASE =
13490
13493
  (import.meta.env.VITE_OLONJS_CLOUD_URL as string | undefined) ??
@@ -1817,11 +1817,14 @@ cat << 'END_OF_FILE_CONTENT' > "package.json"
1817
1817
  "@tiptap/extension-link": "^2.11.5",
1818
1818
  "@tiptap/react": "^2.11.5",
1819
1819
  "@tiptap/starter-kit": "^2.11.5",
1820
- "@olonjs/core": "^1.1.16",
1820
+ "@olonjs/core": "^1.1.17",
1821
+ "@olonjs/react": "^0.1.0",
1822
+ "@olonjs/studio": "^0.1.0",
1821
1823
  "class-variance-authority": "^0.7.1",
1822
1824
  "clsx": "^2.1.1",
1823
1825
  "lucide-react": "^0.474.0",
1824
1826
  "motion": "^12.23.24",
1827
+ "radix-ui": "^1.4.3",
1825
1828
  "react": "^19.0.0",
1826
1829
  "react-markdown": "^9.0.1",
1827
1830
  "react-dom": "^19.0.0",
@@ -2191,8 +2194,6 @@ async function readJsonFile(filePath) {
2191
2194
  }
2192
2195
 
2193
2196
  async function expandCollectionTarget(slug, pageFilePath) {
2194
- if (!/\[[^\]]+\]/.test(slug)) return [slug];
2195
-
2196
2197
  let pageConfig;
2197
2198
  try {
2198
2199
  pageConfig = await readJsonFile(pageFilePath);
@@ -2206,7 +2207,14 @@ async function expandCollectionTarget(slug, pageFilePath) {
2206
2207
  }
2207
2208
 
2208
2209
  const token = `[${binding.paramKey}]`;
2209
- if (!slug.includes(token)) return [slug];
2210
+ // Prefer authored route pattern (page.slug) when the file path is not parametric.
2211
+ const authoredSlug =
2212
+ typeof pageConfig.slug === 'string'
2213
+ ? pageConfig.slug.replace(/\\/g, '/').replace(/^\/+|\/+$/g, '')
2214
+ : '';
2215
+ const routePattern =
2216
+ authoredSlug.includes(token) ? authoredSlug : slug.includes(token) ? slug : '';
2217
+ if (!routePattern) return [slug];
2210
2218
 
2211
2219
  const collectionPath = path.resolve(collectionsDir, binding.source, `${binding.source}.json`);
2212
2220
  let collection;
@@ -2218,7 +2226,9 @@ async function expandCollectionTarget(slug, pageFilePath) {
2218
2226
 
2219
2227
  if (!collection || typeof collection !== 'object' || Array.isArray(collection)) return [slug];
2220
2228
  const itemIds = Object.keys(collection).sort((a, b) => a.localeCompare(b));
2221
- return itemIds.length > 0 ? itemIds.map((itemId) => slug.replace(token, itemId)) : [slug];
2229
+ return itemIds.length > 0
2230
+ ? itemIds.map((itemId) => routePattern.replace(token, itemId))
2231
+ : [slug];
2222
2232
  }
2223
2233
 
2224
2234
  async function listJsonFilesRecursive(dir) {
@@ -2942,10 +2952,9 @@ cat << 'END_OF_FILE_CONTENT' > "src/App.tsx"
2942
2952
  * Bootstrap, persistence, and engine wiring — logic lives in lib/hooks.
2943
2953
  */
2944
2954
  import { useEffect, useMemo } from 'react';
2945
- import { JsonPagesEngine } from '@olonjs/core';
2955
+ import { JsonPagesEngine, OlonFormsContext } from '@olonjs/react';
2946
2956
  import type { JsonPagesConfig, ProjectState } from '@olonjs/core';
2947
2957
  import { withBasePath } from '@olonjs/core';
2948
- import { OlonFormsContext } from '@olonjs/core';
2949
2958
  import { ComponentRegistry } from '@/lib/ComponentRegistry';
2950
2959
  import { CollectionRegistry } from '@/lib/CollectionRegistry';
2951
2960
  import { SECTION_SCHEMAS } from '@/lib/schemas';
@@ -4077,7 +4086,7 @@ END_OF_FILE_CONTENT
4077
4086
  echo "Creating src/components/form-demo/View.tsx..."
4078
4087
  cat << 'END_OF_FILE_CONTENT' > "src/components/form-demo/View.tsx"
4079
4088
  import { Icon } from '@/lib/IconResolver';
4080
- import { useFormState } from '@olonjs/core';
4089
+ import { useFormState } from '@olonjs/react';
4081
4090
  import type { FormDemoData } from './types';
4082
4091
 
4083
4092
  type FormDemoViewProps = {
@@ -5622,7 +5631,8 @@ import {
5622
5631
  Code2, Quote, SquareCode,
5623
5632
  Link2, Unlink2, ImagePlus, Eraser,
5624
5633
  } from 'lucide-react';
5625
- import { STUDIO_EVENTS, useConfig, useStudio } from '@olonjs/core';
5634
+ import { STUDIO_EVENTS } from '@olonjs/core';
5635
+ import { useConfig, useStudio } from '@olonjs/react';
5626
5636
  import type { TiptapData, TiptapSettings } from './types';
5627
5637
 
5628
5638
  // ── UI primitives ─────────────────────────────────────────────────
@@ -8582,7 +8592,7 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/collections/libri/libri.json"
8582
8592
  "id": "1984",
8583
8593
  "title": "1984",
8584
8594
  "author": {
8585
- "$ref": "../autori/autori.json#/alessandro-baricco"
8595
+ "$ref": "../autori/autori.json#/george-orwell"
8586
8596
  },
8587
8597
  "year": 1949,
8588
8598
  "genre": "Distopia",
@@ -9686,14 +9696,8 @@ echo "Creating src/entry-ssg.tsx..."
9686
9696
  cat << 'END_OF_FILE_CONTENT' > "src/entry-ssg.tsx"
9687
9697
  import { renderToString } from 'react-dom/server';
9688
9698
  import { StaticRouter } from 'react-router-dom/server';
9689
- import {
9690
- ConfigProvider,
9691
- PageRenderer,
9692
- StudioProvider,
9693
- contract,
9694
- resolvePageMatchFromRegistry,
9695
- resolveRuntimeConfig,
9696
- } from '@olonjs/core';
9699
+ import { ConfigProvider, PageRenderer, StudioProvider } from '@olonjs/react';
9700
+ import { contract, resolvePageMatchFromRegistry, resolveRuntimeConfig } from '@olonjs/core';
9697
9701
  import type { JsonPagesConfig, PageConfig, SiteConfig, ThemeConfig } from '@/types';
9698
9702
  import { ThemeProvider } from '@/components/ThemeProvider';
9699
9703
  import { ComponentRegistry } from '@/lib/ComponentRegistry';
@@ -11445,7 +11449,6 @@ export function coerceSiteConfig(value: unknown): SiteConfig | null {
11445
11449
  }
11446
11450
  if (!isObjectRecord(input)) return null;
11447
11451
  if (!isObjectRecord(input.identity)) return null;
11448
- if (!Array.isArray(input.pages)) return null;
11449
11452
 
11450
11453
  return input as unknown as SiteConfig;
11451
11454
  }
@@ -11712,7 +11715,6 @@ export function getHydratedData(
11712
11715
  }
11713
11716
 
11714
11717
  END_OF_FILE_CONTENT
11715
- mkdir -p "src/lib/editorial"
11716
11718
  echo "Creating src/lib/getFileCollections.ts..."
11717
11719
  cat << 'END_OF_FILE_CONTENT' > "src/lib/getFileCollections.ts"
11718
11720
  import type { JsonPagesConfig } from '@/types';
@@ -12940,8 +12942,9 @@ function isRemoteStylesheetHref(value: string): boolean {
12940
12942
  export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string[]; rest: string } {
12941
12943
  const hrefs = new Set<string>();
12942
12944
  const leadingTriviaPattern = /^(?:\s+|\/\*[\s\S]*?\*\/)*/;
12945
+ // Vite/Tailwind may emit `@import url("...")` or compacted `@import"https://..."`.
12943
12946
  const importPattern =
12944
- /^@import\s+url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)\s*([^;]*);/i;
12947
+ /^@import(?:\s*url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)|\s*(['"])([^'"]+)\4)\s*([^;]*);/i;
12945
12948
  let rest = cssText;
12946
12949
 
12947
12950
  for (;;) {
@@ -12953,8 +12956,8 @@ export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string
12953
12956
  const match = rest.match(importPattern);
12954
12957
  if (!match) break;
12955
12958
 
12956
- const href = (match[1] ?? match[2] ?? match[3] ?? '').trim();
12957
- const trailingDirectives = (match[4] ?? '').trim();
12959
+ const href = (match[1] ?? match[2] ?? match[3] ?? match[5] ?? '').trim();
12960
+ const trailingDirectives = (match[6] ?? '').trim();
12958
12961
 
12959
12962
  if (!isRemoteStylesheetHref(href) || trailingDirectives.length > 0) {
12960
12963
  break;
@@ -13484,7 +13487,7 @@ END_OF_FILE_CONTENT
13484
13487
  echo "Creating src/lib/useOlonForms.ts..."
13485
13488
  cat << 'END_OF_FILE_CONTENT' > "src/lib/useOlonForms.ts"
13486
13489
  import { useCallback, useEffect, useState } from 'react';
13487
- import type { FormState } from '@olonjs/core';
13490
+ import type { FormState } from '@olonjs/react';
13488
13491
 
13489
13492
  const API_BASE =
13490
13493
  (import.meta.env.VITE_OLONJS_CLOUD_URL as string | undefined) ??
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olonjs/cli",
3
- "version": "3.0.149",
3
+ "version": "3.0.150",
4
4
  "description": "The Sovereign CLI Engine for OlonJS.",
5
5
  "type": "module",
6
6
  "bin": {