Skip to content

Commit b33a05b

Browse files
committed
docs: add template-manifest and date-macros references
1 parent 97efe3b commit b33a05b

8 files changed

Lines changed: 161 additions & 11 deletions

File tree

content/docs/guides/ai-capabilities.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ Use statistical analysis and ML.`,
360360

361361
## Actions as Tools (auto-exposed)
362362

363-
Every declarative {@link Action} you attach to an object is **automatically exposed as an AI tool**, named `action_<actionName>`. When the LLM picks one, the AI runtime dispatches to the same handler Studio's row toolbar would invoke — your business logic stays in one place.
363+
Every declarative `Action` you attach to an object is **automatically exposed as an AI tool**, named `action_<actionName>`. When the LLM picks one, the AI runtime dispatches to the same handler Studio's row toolbar would invoke — your business logic stays in one place.
364364

365365
### What gets exposed
366366

content/docs/references/cloud/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,6 @@ This section contains all protocol schemas for the cloud layer of ObjectStack.
1515
<Card href="/docs/references/cloud/marketplace-admin" title="Marketplace Admin" description="Source: packages/spec/src/cloud/marketplace-admin.zod.ts" />
1616
<Card href="/docs/references/cloud/package" title="Package" description="Source: packages/spec/src/cloud/package.zod.ts" />
1717
<Card href="/docs/references/cloud/package-version" title="Package Version" description="Source: packages/spec/src/cloud/package-version.zod.ts" />
18+
<Card href="/docs/references/cloud/template-manifest" title="Template Manifest" description="Source: packages/spec/src/cloud/template-manifest.zod.ts" />
1819
<Card href="/docs/references/cloud/tenant" title="Tenant" description="Source: packages/spec/src/cloud/tenant.zod.ts" />
1920
</Cards>

content/docs/references/cloud/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"package-version",
1313
"plugin-security",
1414
"provisioning",
15+
"template-manifest",
1516
"tenant"
1617
]
1718
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
title: Template Manifest
3+
description: Template Manifest protocol schemas
4+
---
5+
6+
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */}
7+
8+
`objectstack.manifest.json` — on-disk descriptor for a template / package
9+
10+
source tree. Strict projection of `CreatePackageRequestSchema` (server-
11+
12+
managed fields excluded) plus scaffold-time extras (name slug,
13+
14+
specVersion, skills, preview, scaffold, readmePath).
15+
16+
<Callout type="info">
17+
**Source:** `packages/spec/src/cloud/template-manifest.zod.ts`
18+
</Callout>
19+
20+
## TypeScript Usage
21+
22+
```typescript
23+
import { TemplateManifest } from '@objectstack/spec/cloud';
24+
import type { TemplateManifest } from '@objectstack/spec/cloud';
25+
26+
// Validate data
27+
const result = TemplateManifest.parse(data);
28+
```
29+
30+
---
31+
32+
## TemplateManifest
33+
34+
objectstack.manifest.json — template / package source descriptor
35+
36+
### Properties
37+
38+
| Property | Type | Required | Description |
39+
| :--- | :--- | :--- | :--- |
40+
| **manifestId** | `string` || Globally unique reverse-domain package identifier (e.g. com.acme.crm) |
41+
| **displayName** | `string` || Display name shown in Studio and Marketplace |
42+
| **description** | `string` | optional | Short package description |
43+
| **visibility** | `Enum<'private' \| 'org' \| 'marketplace'>` | optional | Package visibility: private = owner org only; org = all envs in owner org; marketplace = public registry |
44+
| **category** | `string` | optional | Package category for marketplace discovery (e.g. "crm", "hr", "finance", "devtools") |
45+
| **tags** | `string[]` | optional | |
46+
| **iconUrl** | `string` | optional | |
47+
| **homepageUrl** | `string` | optional | |
48+
| **license** | `string` | optional | |
49+
| **publisher** | `Enum<'objectstack' \| 'partner' \| 'community' \| 'private'>` | optional | Package publisher provenance tier |
50+
| **isStarter** | `boolean` | optional | |
51+
| **name** | `string` || CLI slug (kebab-case, no namespace prefix) |
52+
| **specVersion** | `string` || Compatible @objectstack/spec semver range |
53+
| **skills** | `string[]` | optional | Skill ids exercised by this template (for docs / picker) |
54+
| **preview** | `Object` | optional | |
55+
| **scaffold** | `Object` | optional | |
56+
| **readmePath** | `string` | optional | Path (relative to manifest) to long-form README |
57+
58+
59+
---
60+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
---
2+
title: Date Macros
3+
description: Date Macros protocol schemas
4+
---
5+
6+
{/* ⚠️ AUTO-GENERATED — DO NOT EDIT. Run build-docs.ts to regenerate. Hand-written docs go in content/docs/guides/. */}
7+
8+
Date Macro Tokens — the declarative placeholders the UI substitutes
9+
10+
into filter values before sending a query to the data engine.
11+
12+
# Why this lives in `spec`
13+
14+
Filter values in dashboards, views, reports and pages travel as JSON.
15+
16+
Because JSON cannot evaluate code, callers cannot write `daysAgo(30)`
17+
18+
inline; they use a tiny placeholder grammar instead:
19+
20+
\{ published_at: \{ $gte: '\{last_quarter_start\}' \} \}
21+
22+
\{ signal_at: \{ $gte: '\{30_days_ago\}' \} \}
23+
24+
The placeholders are expanded **client-side** by
25+
26+
`resolveDateMacros()` in `@object-ui/core` immediately before the
27+
28+
filter is handed to the data source. The data engine itself only
29+
30+
sees ISO date / timestamp strings, never `\{tokens\}`.
31+
32+
AI agents and template authors author these placeholders directly,
33+
34+
so the **set of recognised tokens is part of the platform contract**
35+
36+
and must live here next to the rest of the JSON-DSL schemas, not
37+
38+
inside any single UI implementation.
39+
40+
# Two flavours of token
41+
42+
1. **Fixed tokens** — small, finite list (`\{today\}`,
43+
44+
`\{current_quarter_start\}`, `\{last_year_end\}`, …). Enumerated by
45+
46+
`DATE_MACRO_TOKENS` below.
47+
48+
2. **Parameterised tokens**`\{N_days_ago\}`, `\{N_weeks_from_now\}`,
49+
50+
etc., where `N` is any non-negative integer. Matched by
51+
52+
`DATE_MACRO_PARAM_RE`. Units: `minute(s)`, `hour(s)`, `day(s)`,
53+
54+
`week(s)`, `month(s)`, `year(s)`. Directions: `ago`, `from_now`.
55+
56+
# Out of scope
57+
58+
- CEL expressions (`cel\`daysAgo(30)\``) run **server-side** in the
59+
60+
formula engine. They are unrelated to these placeholders; see
61+
62+
`@objectstack/formula`.
63+
64+
- Token resolution semantics (week-start day, timezone, fiscal
65+
66+
calendars) are defined by the resolver implementation; spec only
67+
68+
freezes the **vocabulary**.
69+
70+
<Callout type="info">
71+
**Source:** `packages/spec/src/data/date-macros.zod.ts`
72+
</Callout>
73+
74+
## TypeScript Usage
75+
76+
```typescript
77+
import { DateMacroPlaceholder, DateMacroToken } from '@objectstack/spec/data';
78+
import type { DateMacroPlaceholder, DateMacroToken } from '@objectstack/spec/data';
79+
80+
// Validate data
81+
const result = DateMacroPlaceholder.parse(data);
82+
```
83+
84+
---
85+
86+
87+
---
88+
89+
90+
---
91+

content/docs/references/data/index.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This section contains all protocol schemas for the data layer of ObjectStack.
1010
<Card href="/docs/references/data/data-engine" title="Data Engine" description="Source: packages/spec/src/data/data-engine.zod.ts" />
1111
<Card href="/docs/references/data/dataset" title="Dataset" description="Source: packages/spec/src/data/dataset.zod.ts" />
1212
<Card href="/docs/references/data/datasource" title="Datasource" description="Source: packages/spec/src/data/datasource.zod.ts" />
13+
<Card href="/docs/references/data/date-macros" title="Date Macros" description="Source: packages/spec/src/data/date-macros.zod.ts" />
1314
<Card href="/docs/references/data/document" title="Document" description="Source: packages/spec/src/data/document.zod.ts" />
1415
<Card href="/docs/references/data/driver" title="Driver" description="Source: packages/spec/src/data/driver.zod.ts" />
1516
<Card href="/docs/references/data/driver-nosql" title="Driver Nosql" description="Source: packages/spec/src/data/driver-nosql.zod.ts" />

content/docs/references/data/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"data-engine",
66
"dataset",
77
"datasource",
8+
"date-macros",
89
"document",
910
"driver",
1011
"driver-nosql",

packages/runtime/src/app-plugin.test.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ describe('AppPlugin', () => {
174174
expect(mockI18n.setDefaultLocale).toHaveBeenCalledWith('zh-CN');
175175
});
176176

177-
it('should skip translation loading when i18n service is not registered', async () => {
177+
it('should auto-register in-memory i18n fallback when service is not registered', async () => {
178178
vi.mocked(mockContext.getService).mockImplementation((name: string) => {
179179
if (name === 'objectql') return mockQL;
180180
return undefined; // No i18n service
@@ -187,13 +187,11 @@ describe('AppPlugin', () => {
187187
const plugin = new AppPlugin(bundle);
188188
await plugin.start!(mockContext);
189189

190-
// Should log warning (translations exist but no i18n service) and not throw
191-
expect(mockContext.logger.warn).toHaveBeenCalledWith(
192-
expect.stringContaining('no i18n service is registered')
193-
);
190+
// Auto-registers in-memory fallback and loads translations; does not throw or warn.
191+
expect(mockContext.registerService).toHaveBeenCalledWith('i18n', expect.any(Object));
194192
});
195193

196-
it('should skip translation loading when getService throws for i18n', async () => {
194+
it('should auto-register in-memory i18n fallback when getService throws for i18n', async () => {
197195
vi.mocked(mockContext.getService).mockImplementation((name: string) => {
198196
if (name === 'objectql') return mockQL;
199197
throw new Error("[Kernel] Service 'i18n' not found");
@@ -206,10 +204,7 @@ describe('AppPlugin', () => {
206204
const plugin = new AppPlugin(bundle);
207205
await plugin.start!(mockContext);
208206

209-
// Should log warning (translations exist but no i18n service) and not throw
210-
expect(mockContext.logger.warn).toHaveBeenCalledWith(
211-
expect.stringContaining('no i18n service is registered')
212-
);
207+
expect(mockContext.registerService).toHaveBeenCalledWith('i18n', expect.any(Object));
213208
});
214209

215210
it('should handle bundle with no translations gracefully', async () => {

0 commit comments

Comments
 (0)