@wix/origami-site 0.0.0-stage → 0.1.0
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/package.json +68 -3
- package/src/browser/index.d.ts +10 -0
- package/src/browser/index.js +1 -0
- package/src/default-error-404.jsx +9 -0
- package/src/popups/index.d.ts +3 -0
- package/src/popups/index.js +1 -0
- package/src/server/index.d.ts +80 -0
- package/src/server/index.js +1 -0
- package/src/server/requests/errors.d.ts +23 -0
- package/src/server/requests/index.js +1 -0
- package/src/server/site-tree/index.js +1 -0
- package/src/styles.d.ts +2 -0
- package/src/types/index.d.ts +48 -0
- package/src/types/index.js +1 -0
- package/src/vite-plugins/index.d.ts +2 -0
- package/src/vite-plugins/index.js +1 -0
- package/README.md +0 -3
package/package.json
CHANGED
|
@@ -1,6 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/origami-site",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Runs an exported Wix origami site: file-based routing, Wix dynamic pages, popups and build checks. Use with @wix/origami-site-astro or @wix/origami-site-express.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"src"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc --noEmit",
|
|
11
|
+
"lint": "oxlint .",
|
|
12
|
+
"test": "tsc --noEmit -p tsconfig.test.json"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "^22.0.0",
|
|
16
|
+
"typescript": "^6.0.3",
|
|
17
|
+
"vite": "^8"
|
|
18
|
+
},
|
|
19
|
+
"publishUnscoped": false,
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"registry": "https://registry.npmjs.org/",
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"wix": {
|
|
25
|
+
"artifact": {
|
|
26
|
+
"groupId": "com.wixpress.npm",
|
|
27
|
+
"artifactId": "origami-site",
|
|
28
|
+
"targets": {
|
|
29
|
+
"docker": false
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"validations": {
|
|
33
|
+
"source": [
|
|
34
|
+
"lint"
|
|
35
|
+
],
|
|
36
|
+
"postBuild": [
|
|
37
|
+
"test"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@wix/origami-types": "1.2.0",
|
|
43
|
+
"react": "^18.3.1",
|
|
44
|
+
"react-dom": "^18.3.1",
|
|
45
|
+
"@wix/builder-error-pages": "^1.1.6",
|
|
46
|
+
"@wix/builder-piler-components": "^1.6.7"
|
|
47
|
+
},
|
|
48
|
+
"exports": {
|
|
49
|
+
"./server": {
|
|
50
|
+
"types": "./src/server/index.d.ts",
|
|
51
|
+
"default": "./src/server/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./browser": {
|
|
54
|
+
"types": "./src/browser/index.d.ts",
|
|
55
|
+
"default": "./src/browser/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./popups": {
|
|
58
|
+
"types": "./src/popups/index.d.ts",
|
|
59
|
+
"default": "./src/popups/index.js"
|
|
60
|
+
},
|
|
61
|
+
"./vite-plugins": {
|
|
62
|
+
"types": "./src/vite-plugins/index.d.ts",
|
|
63
|
+
"default": "./src/vite-plugins/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./types": {
|
|
66
|
+
"types": "./src/types/index.d.ts"
|
|
67
|
+
},
|
|
68
|
+
"./default-error-404": "./src/default-error-404.jsx"
|
|
69
|
+
},
|
|
70
|
+
"falconPackageHash": "88d8479096308cdba298b8fe696e53dbd9a3482bd149a332bd45b100"
|
|
6
71
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PageData } from '../server/index.js'
|
|
2
|
+
// PLAN-QUESTION: mountPage options follow the example; page modules remain unknown until milestone 1.7.
|
|
3
|
+
export type MountPageOptions = {
|
|
4
|
+
pages: Record<string, () => Promise<unknown>>
|
|
5
|
+
popups: Record<string, () => Promise<unknown>>
|
|
6
|
+
seoUriByPageId: Record<string, string>
|
|
7
|
+
beforeMount: () => Promise<unknown>
|
|
8
|
+
}
|
|
9
|
+
export function mountPage(element: Element | null, options: MountPageOptions): Promise<() => void>
|
|
10
|
+
export function readPageData(): PageData
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { createRoot } from 'react-dom/client'
|
|
3
|
+
import { DefaultError404 } from '@wix/builder-error-pages'
|
|
4
|
+
import { PilerPage } from '@wix/builder-piler-components'
|
|
5
|
+
import '@wix/builder-error-pages/style.css'
|
|
6
|
+
|
|
7
|
+
createRoot(document.getElementById('root')).render(
|
|
8
|
+
React.createElement(React.StrictMode, null, React.createElement(PilerPage, { Page: DefaultError404 }))
|
|
9
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { SiteRouteTable, PageRoute, RouterRoute, AccessRule } from '@wix/origami-types'
|
|
2
|
+
export type { AccessRule } from '@wix/origami-types'
|
|
3
|
+
// PLAN-QUESTION: Logger is unnamed structurally in the plan; only warn/error are used.
|
|
4
|
+
export type Logger = Pick<Console, 'warn' | 'error'>
|
|
5
|
+
export type RequestContext = { request: Request; url: URL; tokens: TokenProvider; locals: Map<string, unknown> }
|
|
6
|
+
|
|
7
|
+
export type SiteOptions = {
|
|
8
|
+
root: string // the site package folder
|
|
9
|
+
mode: 'dev' | 'prod'
|
|
10
|
+
table?: SiteRouteTable // prod: the table from the build. dev: omitted, the core scans.
|
|
11
|
+
wix: { clientId: string; siteId: string } // from VITE_WIX_CLIENT_ID / VITE_WIX_SITE_ID
|
|
12
|
+
tokens?: TokenProvider // default: builderAuthTokenProvider (3.3)
|
|
13
|
+
access?: AccessSource // default: noAccessRules (4)
|
|
14
|
+
accessHandlers?: AccessHandler[] // default: []
|
|
15
|
+
fetch?: typeof fetch // tests inject a fake
|
|
16
|
+
wixApiBaseUrl?: string // default 'https://www.wixapis.com'; the conformance suite points it at the fake
|
|
17
|
+
routerTimeoutMs?: number // default 5000
|
|
18
|
+
logger?: Logger // default: console with an [origami] prefix
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface OrigamiSite {
|
|
22
|
+
/** Current route table (dev: rescans if dirty). */
|
|
23
|
+
table(): Promise<SiteRouteTable>
|
|
24
|
+
/** Reference URL matcher. Pure, no network. */
|
|
25
|
+
match(url: URL): Promise<RouteMatch>
|
|
26
|
+
/** Answer one request. Never throws: errors become a Resolution. */
|
|
27
|
+
handle(request: Request): Promise<Resolution>
|
|
28
|
+
/** Dev: tell the core a file changed (adapters forward Vite watcher events). */
|
|
29
|
+
fileChanged(path: string): void
|
|
30
|
+
/** Dev: subscribe to table changes, e.g. to invalidate the virtual:origami-site module. */
|
|
31
|
+
onTableChange(listener: (table: SiteRouteTable) => void): () => void
|
|
32
|
+
close(): Promise<void>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type RouteMatch =
|
|
36
|
+
| { kind: 'page'; route: PageRoute }
|
|
37
|
+
| { kind: 'router'; route: RouterRoute; suffix: string } // '/a/b/c'; '/' for bare '/team'
|
|
38
|
+
| { kind: 'reserved'; path: string } // /_origami/*
|
|
39
|
+
| { kind: 'notFound' }
|
|
40
|
+
|
|
41
|
+
export type Resolution =
|
|
42
|
+
| { kind: 'page'; status: 200 | 404; page: PageRef; data: PageData; headers: Headers }
|
|
43
|
+
| { kind: 'response'; response: Response } // redirects, reserved endpoints, 405, 503
|
|
44
|
+
|
|
45
|
+
export type PageRef = { key: string; itemPath?: string; title: string }
|
|
46
|
+
|
|
47
|
+
export type PageData = {
|
|
48
|
+
page: string // PageRef.key; the browser loads this page
|
|
49
|
+
route: { kind: 'page' | 'router' | 'notFound'; url: string; role?: string }
|
|
50
|
+
services: Record<string, unknown> // runtime configs merged into the page's services
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface TokenProvider {
|
|
54
|
+
/** The access token to use for this request. Called at most once per request (memoised in the context). */
|
|
55
|
+
getAccessToken(request: Request): Promise<string>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// AccessRule is shared with route types. // e.g. { type: 'members' }, { type: 'password' }
|
|
59
|
+
|
|
60
|
+
/** Where rules come from: a file next to the page, a central file, … — not decided. One swappable loader. */
|
|
61
|
+
export interface AccessSource {
|
|
62
|
+
load(table: SiteRouteTable, root: string): Promise<Map<string /* route key */, AccessRule[]>>
|
|
63
|
+
}
|
|
64
|
+
export const noAccessRules: AccessSource
|
|
65
|
+
|
|
66
|
+
/** One handler per rule type. Returns null to allow, or a Response (redirect, 401, a form). */
|
|
67
|
+
export interface AccessHandler {
|
|
68
|
+
type: string
|
|
69
|
+
check(rule: AccessRule, request: Request, ctx: RequestContext): Promise<Response | null>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
export type { SiteTreeError, RouterServiceError } from './requests/errors.js'
|
|
74
|
+
export function createSite(options: SiteOptions): Promise<OrigamiSite>
|
|
75
|
+
export function readSiteTree(root: string): Promise<SiteRouteTable>
|
|
76
|
+
export function runInRequestContext<T>(ctx: RequestContext, fn: () => Promise<T>): Promise<T>
|
|
77
|
+
export function getRequestContext(): RequestContext
|
|
78
|
+
export function getAccessToken(): Promise<string>
|
|
79
|
+
export function serializePageData(data: PageData): string
|
|
80
|
+
export function builderAuthTokenProvider(options: { clientId: string; siteId: string }): TokenProvider
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export class SiteTreeError extends Error {
|
|
2
|
+
code:
|
|
3
|
+
| 'DUPLICATE_URL' // two folders give the same URL
|
|
4
|
+
| 'ROUTE_JSON_INVALID' // not JSON, or a required field missing or of the wrong type
|
|
5
|
+
| 'ROUTE_JSON_MISSING_SERVICE_URL' // no routerServiceUrl: origami refuses to start
|
|
6
|
+
| 'ROUTE_JSON_SIBLINGS_DIFFER' // [a]/route.json and [b]/route.json differ
|
|
7
|
+
| 'ROLE_FOLDER_MISSING' // pages.member = 'team-member' but no [team-member]/ folder
|
|
8
|
+
| 'ROLE_FOLDER_NOT_IN_PAGES' // a [x]/ folder that no role in pages names
|
|
9
|
+
| 'BRACKET_OUTSIDE_PREFIX' // [x]/ not directly under a prefix folder
|
|
10
|
+
| 'PREFIX_HAS_FILES' // team/ itself holds page files
|
|
11
|
+
| 'ROLE_PAGE_HAS_CHILDREN' // a folder inside [x]/ that isn't _generated
|
|
12
|
+
| 'PREFIX_COLLIDES_WITH_PAGE' // pages/team is both a page and a prefix
|
|
13
|
+
| 'NOT_FOUND_HAS_CHILDREN'
|
|
14
|
+
| 'DUPLICATE_POPUP'
|
|
15
|
+
| 'UNSUPPORTED_ACCESS_RULE' // see section 4
|
|
16
|
+
paths: string[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class RouterServiceError extends Error {
|
|
20
|
+
code: 'TIMEOUT' | 'NETWORK' | 'HTTP_STATUS' | 'BAD_RESPONSE'
|
|
21
|
+
routerPrefix: string
|
|
22
|
+
status?: number
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/src/styles.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** What each adapter package exports as its default `origami` descriptor. */
|
|
2
|
+
export interface OrigamiAdapter {
|
|
3
|
+
name: string // '@wix/origami-site-astro'
|
|
4
|
+
version: string // its package version
|
|
5
|
+
framework: { name: string; range: string } // { name: 'astro', range: '^7.3.0' }
|
|
6
|
+
/** Files and package.json fields the generator writes for this adapter (section 8). */
|
|
7
|
+
project(ctx: ProjectContext): ProjectFiles
|
|
8
|
+
/** How the conformance suite runs a site with this adapter. */
|
|
9
|
+
conformance: ConformanceDriver
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type ProjectContext = {
|
|
13
|
+
siteName: string
|
|
14
|
+
coreVersion: string // the @wix/origami-site range to depend on
|
|
15
|
+
nodeVersion: string // '22'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type ProjectFiles = {
|
|
19
|
+
files: Record<string /* path relative to the site package */, string /* contents */> // e.g. astro.config.mjs, Dockerfile
|
|
20
|
+
packageJson: {
|
|
21
|
+
scripts: { dev: string; build: string; start: string } & Record<string, string>
|
|
22
|
+
dependencies: Record<string, string>
|
|
23
|
+
devDependencies?: Record<string, string>
|
|
24
|
+
}
|
|
25
|
+
readme: string // markdown section appended to the site README
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface ConformanceDriver {
|
|
29
|
+
/** Start `yarn dev`. Resolves when the server answers. */
|
|
30
|
+
dev(root: string, env: SiteEnv): Promise<RunningSite>
|
|
31
|
+
// PLAN-QUESTION: Keep the explicit BuildResult union; rejection policy is deferred to adapters.
|
|
32
|
+
/** Run `yarn build`. */
|
|
33
|
+
build(root: string, env: SiteEnv): Promise<BuildResult>
|
|
34
|
+
/** Start `yarn start` after a build. */
|
|
35
|
+
start(root: string, env: SiteEnv): Promise<RunningSite>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type SiteEnv = Record<string, string> // VITE_WIX_CLIENT_ID, VITE_WIX_SITE_ID, ORIGAMI_WIX_API_BASE (tests), PORT
|
|
39
|
+
export type RunningSite = { url: URL; logs(): string; restarts(): number; stop(): Promise<void> }
|
|
40
|
+
export type BuildResult = { ok: true; output: string } | { ok: false; output: string }
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
/** Core contracts only; runtime APIs belong to @wix/origami-site/server. */
|
|
44
|
+
export type {
|
|
45
|
+
SiteOptions, OrigamiSite, RouteMatch, Resolution, PageRef, PageData,
|
|
46
|
+
RequestContext, TokenProvider, AccessRule, AccessSource, AccessHandler,
|
|
47
|
+
Logger, SiteTreeError, RouterServiceError,
|
|
48
|
+
} from '../server/index.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/README.md
DELETED