@olonjs/cli 3.0.149 → 3.0.151

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.18",
1821
+ "@olonjs/react": "^0.1.1",
1822
+ "@olonjs/studio": "^0.1.1",
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';
@@ -3052,6 +3061,8 @@ function App() {
3052
3061
  bootstrap.isHotSaveMode || Object.keys(bootstrap.collections).length > 0
3053
3062
  ? bootstrap.collections
3054
3063
  : fileCollections;
3064
+
3065
+ // TOASK: why this if we have a menuConfig Object?
3055
3066
  const engineRefDocuments = useMemo(
3056
3067
  () => ({
3057
3068
  'menu.json': bootstrap.menuConfig,
@@ -3060,7 +3071,7 @@ function App() {
3060
3071
  }),
3061
3072
  [bootstrap.menuConfig],
3062
3073
  );
3063
-
3074
+ // TOASK END
3064
3075
  const config: JsonPagesConfig = {
3065
3076
  tenantId: TENANT_ID,
3066
3077
  basePath: APP_BASE_PATH,
@@ -4077,7 +4088,7 @@ END_OF_FILE_CONTENT
4077
4088
  echo "Creating src/components/form-demo/View.tsx..."
4078
4089
  cat << 'END_OF_FILE_CONTENT' > "src/components/form-demo/View.tsx"
4079
4090
  import { Icon } from '@/lib/IconResolver';
4080
- import { useFormState } from '@olonjs/core';
4091
+ import { useFormState } from '@olonjs/react';
4081
4092
  import type { FormDemoData } from './types';
4082
4093
 
4083
4094
  type FormDemoViewProps = {
@@ -5622,7 +5633,8 @@ import {
5622
5633
  Code2, Quote, SquareCode,
5623
5634
  Link2, Unlink2, ImagePlus, Eraser,
5624
5635
  } from 'lucide-react';
5625
- import { STUDIO_EVENTS, useConfig, useStudio } from '@olonjs/core';
5636
+ import { STUDIO_EVENTS } from '@olonjs/core';
5637
+ import { useConfig, useStudio } from '@olonjs/react';
5626
5638
  import type { TiptapData, TiptapSettings } from './types';
5627
5639
 
5628
5640
  // ── UI primitives ─────────────────────────────────────────────────
@@ -8582,7 +8594,7 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/collections/libri/libri.json"
8582
8594
  "id": "1984",
8583
8595
  "title": "1984",
8584
8596
  "author": {
8585
- "$ref": "../autori/autori.json#/alessandro-baricco"
8597
+ "$ref": "../autori/autori.json#/george-orwell"
8586
8598
  },
8587
8599
  "year": 1949,
8588
8600
  "genre": "Distopia",
@@ -9686,14 +9698,8 @@ echo "Creating src/entry-ssg.tsx..."
9686
9698
  cat << 'END_OF_FILE_CONTENT' > "src/entry-ssg.tsx"
9687
9699
  import { renderToString } from 'react-dom/server';
9688
9700
  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';
9701
+ import { ConfigProvider, PageRenderer, StudioProvider } from '@olonjs/react';
9702
+ import { contract, resolvePageMatchFromRegistry, resolveRuntimeConfig } from '@olonjs/core';
9697
9703
  import type { JsonPagesConfig, PageConfig, SiteConfig, ThemeConfig } from '@/types';
9698
9704
  import { ThemeProvider } from '@/components/ThemeProvider';
9699
9705
  import { ComponentRegistry } from '@/lib/ComponentRegistry';
@@ -11445,7 +11451,6 @@ export function coerceSiteConfig(value: unknown): SiteConfig | null {
11445
11451
  }
11446
11452
  if (!isObjectRecord(input)) return null;
11447
11453
  if (!isObjectRecord(input.identity)) return null;
11448
- if (!Array.isArray(input.pages)) return null;
11449
11454
 
11450
11455
  return input as unknown as SiteConfig;
11451
11456
  }
@@ -11712,7 +11717,6 @@ export function getHydratedData(
11712
11717
  }
11713
11718
 
11714
11719
  END_OF_FILE_CONTENT
11715
- mkdir -p "src/lib/editorial"
11716
11720
  echo "Creating src/lib/getFileCollections.ts..."
11717
11721
  cat << 'END_OF_FILE_CONTENT' > "src/lib/getFileCollections.ts"
11718
11722
  import type { JsonPagesConfig } from '@/types';
@@ -12940,8 +12944,9 @@ function isRemoteStylesheetHref(value: string): boolean {
12940
12944
  export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string[]; rest: string } {
12941
12945
  const hrefs = new Set<string>();
12942
12946
  const leadingTriviaPattern = /^(?:\s+|\/\*[\s\S]*?\*\/)*/;
12947
+ // Vite/Tailwind may emit `@import url("...")` or compacted `@import"https://..."`.
12943
12948
  const importPattern =
12944
- /^@import\s+url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)\s*([^;]*);/i;
12949
+ /^@import(?:\s*url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)|\s*(['"])([^'"]+)\4)\s*([^;]*);/i;
12945
12950
  let rest = cssText;
12946
12951
 
12947
12952
  for (;;) {
@@ -12953,8 +12958,8 @@ export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string
12953
12958
  const match = rest.match(importPattern);
12954
12959
  if (!match) break;
12955
12960
 
12956
- const href = (match[1] ?? match[2] ?? match[3] ?? '').trim();
12957
- const trailingDirectives = (match[4] ?? '').trim();
12961
+ const href = (match[1] ?? match[2] ?? match[3] ?? match[5] ?? '').trim();
12962
+ const trailingDirectives = (match[6] ?? '').trim();
12958
12963
 
12959
12964
  if (!isRemoteStylesheetHref(href) || trailingDirectives.length > 0) {
12960
12965
  break;
@@ -13484,7 +13489,7 @@ END_OF_FILE_CONTENT
13484
13489
  echo "Creating src/lib/useOlonForms.ts..."
13485
13490
  cat << 'END_OF_FILE_CONTENT' > "src/lib/useOlonForms.ts"
13486
13491
  import { useCallback, useEffect, useState } from 'react';
13487
- import type { FormState } from '@olonjs/core';
13492
+ import type { FormState } from '@olonjs/react';
13488
13493
 
13489
13494
  const API_BASE =
13490
13495
  (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.18",
1821
+ "@olonjs/react": "^0.1.1",
1822
+ "@olonjs/studio": "^0.1.1",
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';
@@ -3052,6 +3061,8 @@ function App() {
3052
3061
  bootstrap.isHotSaveMode || Object.keys(bootstrap.collections).length > 0
3053
3062
  ? bootstrap.collections
3054
3063
  : fileCollections;
3064
+
3065
+ // TOASK: why this if we have a menuConfig Object?
3055
3066
  const engineRefDocuments = useMemo(
3056
3067
  () => ({
3057
3068
  'menu.json': bootstrap.menuConfig,
@@ -3060,7 +3071,7 @@ function App() {
3060
3071
  }),
3061
3072
  [bootstrap.menuConfig],
3062
3073
  );
3063
-
3074
+ // TOASK END
3064
3075
  const config: JsonPagesConfig = {
3065
3076
  tenantId: TENANT_ID,
3066
3077
  basePath: APP_BASE_PATH,
@@ -4077,7 +4088,7 @@ END_OF_FILE_CONTENT
4077
4088
  echo "Creating src/components/form-demo/View.tsx..."
4078
4089
  cat << 'END_OF_FILE_CONTENT' > "src/components/form-demo/View.tsx"
4079
4090
  import { Icon } from '@/lib/IconResolver';
4080
- import { useFormState } from '@olonjs/core';
4091
+ import { useFormState } from '@olonjs/react';
4081
4092
  import type { FormDemoData } from './types';
4082
4093
 
4083
4094
  type FormDemoViewProps = {
@@ -5622,7 +5633,8 @@ import {
5622
5633
  Code2, Quote, SquareCode,
5623
5634
  Link2, Unlink2, ImagePlus, Eraser,
5624
5635
  } from 'lucide-react';
5625
- import { STUDIO_EVENTS, useConfig, useStudio } from '@olonjs/core';
5636
+ import { STUDIO_EVENTS } from '@olonjs/core';
5637
+ import { useConfig, useStudio } from '@olonjs/react';
5626
5638
  import type { TiptapData, TiptapSettings } from './types';
5627
5639
 
5628
5640
  // ── UI primitives ─────────────────────────────────────────────────
@@ -8582,7 +8594,7 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/collections/libri/libri.json"
8582
8594
  "id": "1984",
8583
8595
  "title": "1984",
8584
8596
  "author": {
8585
- "$ref": "../autori/autori.json#/alessandro-baricco"
8597
+ "$ref": "../autori/autori.json#/george-orwell"
8586
8598
  },
8587
8599
  "year": 1949,
8588
8600
  "genre": "Distopia",
@@ -9686,14 +9698,8 @@ echo "Creating src/entry-ssg.tsx..."
9686
9698
  cat << 'END_OF_FILE_CONTENT' > "src/entry-ssg.tsx"
9687
9699
  import { renderToString } from 'react-dom/server';
9688
9700
  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';
9701
+ import { ConfigProvider, PageRenderer, StudioProvider } from '@olonjs/react';
9702
+ import { contract, resolvePageMatchFromRegistry, resolveRuntimeConfig } from '@olonjs/core';
9697
9703
  import type { JsonPagesConfig, PageConfig, SiteConfig, ThemeConfig } from '@/types';
9698
9704
  import { ThemeProvider } from '@/components/ThemeProvider';
9699
9705
  import { ComponentRegistry } from '@/lib/ComponentRegistry';
@@ -11445,7 +11451,6 @@ export function coerceSiteConfig(value: unknown): SiteConfig | null {
11445
11451
  }
11446
11452
  if (!isObjectRecord(input)) return null;
11447
11453
  if (!isObjectRecord(input.identity)) return null;
11448
- if (!Array.isArray(input.pages)) return null;
11449
11454
 
11450
11455
  return input as unknown as SiteConfig;
11451
11456
  }
@@ -11712,7 +11717,6 @@ export function getHydratedData(
11712
11717
  }
11713
11718
 
11714
11719
  END_OF_FILE_CONTENT
11715
- mkdir -p "src/lib/editorial"
11716
11720
  echo "Creating src/lib/getFileCollections.ts..."
11717
11721
  cat << 'END_OF_FILE_CONTENT' > "src/lib/getFileCollections.ts"
11718
11722
  import type { JsonPagesConfig } from '@/types';
@@ -12940,8 +12944,9 @@ function isRemoteStylesheetHref(value: string): boolean {
12940
12944
  export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string[]; rest: string } {
12941
12945
  const hrefs = new Set<string>();
12942
12946
  const leadingTriviaPattern = /^(?:\s+|\/\*[\s\S]*?\*\/)*/;
12947
+ // Vite/Tailwind may emit `@import url("...")` or compacted `@import"https://..."`.
12943
12948
  const importPattern =
12944
- /^@import\s+url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)\s*([^;]*);/i;
12949
+ /^@import(?:\s*url\(\s*(?:'([^']+)'|"([^"]+)"|([^'")\s][^)]*))\s*\)|\s*(['"])([^'"]+)\4)\s*([^;]*);/i;
12945
12950
  let rest = cssText;
12946
12951
 
12947
12952
  for (;;) {
@@ -12953,8 +12958,8 @@ export function extractLeadingRemoteCssImports(cssText: string): { hrefs: string
12953
12958
  const match = rest.match(importPattern);
12954
12959
  if (!match) break;
12955
12960
 
12956
- const href = (match[1] ?? match[2] ?? match[3] ?? '').trim();
12957
- const trailingDirectives = (match[4] ?? '').trim();
12961
+ const href = (match[1] ?? match[2] ?? match[3] ?? match[5] ?? '').trim();
12962
+ const trailingDirectives = (match[6] ?? '').trim();
12958
12963
 
12959
12964
  if (!isRemoteStylesheetHref(href) || trailingDirectives.length > 0) {
12960
12965
  break;
@@ -13484,7 +13489,7 @@ END_OF_FILE_CONTENT
13484
13489
  echo "Creating src/lib/useOlonForms.ts..."
13485
13490
  cat << 'END_OF_FILE_CONTENT' > "src/lib/useOlonForms.ts"
13486
13491
  import { useCallback, useEffect, useState } from 'react';
13487
- import type { FormState } from '@olonjs/core';
13492
+ import type { FormState } from '@olonjs/react';
13488
13493
 
13489
13494
  const API_BASE =
13490
13495
  (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.151",
4
4
  "description": "The Sovereign CLI Engine for OlonJS.",
5
5
  "type": "module",
6
6
  "bin": {