@ossy/app 1.16.5 → 1.16.7
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/cli/build.task.js +21 -2
- package/cli/get-platform-files.task.js +20 -11
- package/cli/manifest-plugin.js +31 -3
- package/package.json +12 -12
- package/src/index.js +1 -0
package/cli/build.task.js
CHANGED
|
@@ -13,10 +13,11 @@ import getPlatformFiles, {
|
|
|
13
13
|
PAGE_FILE_PATTERN,
|
|
14
14
|
API_FILE_PATTERN,
|
|
15
15
|
TASK_FILE_PATTERN,
|
|
16
|
+
RESOURCE_FILE_PATTERN,
|
|
16
17
|
} from './get-platform-files.task.js'
|
|
17
18
|
import { manifestPlugin } from './manifest-plugin.js'
|
|
18
19
|
|
|
19
|
-
export { PAGE_FILE_PATTERN, API_FILE_PATTERN, TASK_FILE_PATTERN }
|
|
20
|
+
export { PAGE_FILE_PATTERN, API_FILE_PATTERN, TASK_FILE_PATTERN, RESOURCE_FILE_PATTERN }
|
|
20
21
|
|
|
21
22
|
// Generated entry stubs live under `build/.ossy/entries/`. Putting them
|
|
22
23
|
// inside `build/` means they're cleaned automatically with every build,
|
|
@@ -113,9 +114,22 @@ function generateTaskStub ({ stubAbs, sourceAbs }) {
|
|
|
113
114
|
].join('\n')
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
// Resources are pure data (POJOs default-exported from `*.resource.js`).
|
|
118
|
+
// The stub only pass-through re-exports the default so the manifest plugin
|
|
119
|
+
// can read it via the same `await import(chunkUrl)` path as the other kinds.
|
|
120
|
+
function generateResourceStub ({ stubAbs, sourceAbs }) {
|
|
121
|
+
const importPath = relImport(stubAbs, sourceAbs)
|
|
122
|
+
return [
|
|
123
|
+
'// Generated by @ossy/app — do not edit',
|
|
124
|
+
`export { default } from '${importPath}'`,
|
|
125
|
+
'',
|
|
126
|
+
].join('\n')
|
|
127
|
+
}
|
|
128
|
+
|
|
116
129
|
function stubFor (kind, args) {
|
|
117
130
|
if (kind === 'page') return generatePageStub(args)
|
|
118
131
|
if (kind === 'api') return generateApiStub(args)
|
|
132
|
+
if (kind === 'resource') return generateResourceStub(args)
|
|
119
133
|
return generateTaskStub(args)
|
|
120
134
|
}
|
|
121
135
|
|
|
@@ -151,7 +165,12 @@ export async function build (cliArgs = []) {
|
|
|
151
165
|
ensureDir(stubDir)
|
|
152
166
|
|
|
153
167
|
const platformFiles = await getPlatformFiles(srcDir)
|
|
154
|
-
const allEntries = [
|
|
168
|
+
const allEntries = [
|
|
169
|
+
...platformFiles.pages,
|
|
170
|
+
...platformFiles.apis,
|
|
171
|
+
...platformFiles.tasks,
|
|
172
|
+
...platformFiles.resources,
|
|
173
|
+
]
|
|
155
174
|
|
|
156
175
|
const entriesByStub = new Map()
|
|
157
176
|
const stubInputMap = {}
|
|
@@ -4,21 +4,22 @@ import path from 'node:path'
|
|
|
4
4
|
export const PAGE_FILE_PATTERN = /\.page\.(jsx?|tsx?)$/
|
|
5
5
|
export const API_FILE_PATTERN = /\.api\.(mjs|cjs|js)$/
|
|
6
6
|
export const TASK_FILE_PATTERN = /\.task\.(mjs|cjs|js)$/
|
|
7
|
+
export const RESOURCE_FILE_PATTERN = /\.resource\.(mjs|cjs|js)$/
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
|
-
* @typedef {'page' | 'api' | 'task'} EntryKind
|
|
10
|
+
* @typedef {'page' | 'api' | 'task' | 'resource'} EntryKind
|
|
10
11
|
*
|
|
11
12
|
* @typedef {object} PlatformEntry
|
|
12
13
|
* @property {EntryKind} kind Which bucket this entry lives in.
|
|
13
14
|
* @property {string} sourcePath Absolute path to the user-authored source file.
|
|
14
15
|
*
|
|
15
16
|
* @typedef {object} PlatformFiles
|
|
16
|
-
* @property {PlatformEntry[]} pages
|
|
17
|
-
* @property {PlatformEntry[]} apis
|
|
18
|
-
* @property {PlatformEntry[]} tasks
|
|
17
|
+
* @property {PlatformEntry[]} pages Discovered `*.page.{jsx,tsx,...}` entries.
|
|
18
|
+
* @property {PlatformEntry[]} apis Discovered `*.api.{js,mjs,cjs}` entries.
|
|
19
|
+
* @property {PlatformEntry[]} tasks Discovered `*.task.{js,mjs,cjs}` entries.
|
|
20
|
+
* @property {PlatformEntry[]} resources Discovered `*.resource.{js,mjs,cjs}` entries.
|
|
19
21
|
*/
|
|
20
|
-
|
|
21
|
-
function discoverFilesByPattern (srcDir, filePattern) {
|
|
22
|
+
export function discoverFilesByPattern (srcDir, filePattern) {
|
|
22
23
|
const dir = path.resolve(srcDir)
|
|
23
24
|
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) return []
|
|
24
25
|
const files = []
|
|
@@ -38,6 +39,7 @@ function classifyFile (absPath) {
|
|
|
38
39
|
if (PAGE_FILE_PATTERN.test(base)) return 'page'
|
|
39
40
|
if (API_FILE_PATTERN.test(base)) return 'api'
|
|
40
41
|
if (TASK_FILE_PATTERN.test(base)) return 'task'
|
|
42
|
+
if (RESOURCE_FILE_PATTERN.test(base)) return 'resource'
|
|
41
43
|
return null
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -66,6 +68,14 @@ export function defaultPageRoute (id) {
|
|
|
66
68
|
return id === 'home' ? '/' : '/' + id
|
|
67
69
|
}
|
|
68
70
|
|
|
71
|
+
/**
|
|
72
|
+
* @returns {{ id: string, path: string }}
|
|
73
|
+
*/
|
|
74
|
+
export function filePathToRoute (absPath, srcDir) {
|
|
75
|
+
const id = metadataIdFromFile(absPath, srcDir)
|
|
76
|
+
return { id, path: defaultPageRoute(id) }
|
|
77
|
+
}
|
|
78
|
+
|
|
69
79
|
/**
|
|
70
80
|
* Walks `srcDir` and returns the user-authored entries the platform cares
|
|
71
81
|
* about, bucketed by kind. Empty (zero-byte) source files are skipped — we
|
|
@@ -79,21 +89,20 @@ export function defaultPageRoute (id) {
|
|
|
79
89
|
* @returns {Promise<PlatformFiles>}
|
|
80
90
|
*/
|
|
81
91
|
export default async function getPlatformFiles (srcDir) {
|
|
82
|
-
const out = { pages: [], apis: [], tasks: [] }
|
|
92
|
+
const out = { pages: [], apis: [], tasks: [], resources: [] }
|
|
83
93
|
const all = [
|
|
84
94
|
...discoverFilesByPattern(srcDir, PAGE_FILE_PATTERN),
|
|
85
95
|
...discoverFilesByPattern(srcDir, API_FILE_PATTERN),
|
|
86
96
|
...discoverFilesByPattern(srcDir, TASK_FILE_PATTERN),
|
|
97
|
+
...discoverFilesByPattern(srcDir, RESOURCE_FILE_PATTERN),
|
|
87
98
|
]
|
|
99
|
+
const bucketByKind = { page: 'pages', api: 'apis', task: 'tasks', resource: 'resources' }
|
|
88
100
|
for (const sourcePath of all) {
|
|
89
101
|
const stat = fs.statSync(sourcePath)
|
|
90
102
|
if (!stat.isFile() || stat.size === 0) continue
|
|
91
103
|
const kind = classifyFile(sourcePath)
|
|
92
104
|
if (!kind) continue
|
|
93
|
-
out[kind
|
|
94
|
-
kind,
|
|
95
|
-
sourcePath,
|
|
96
|
-
})
|
|
105
|
+
out[bucketByKind[kind]].push({ kind, sourcePath })
|
|
97
106
|
}
|
|
98
107
|
return out
|
|
99
108
|
}
|
package/cli/manifest-plugin.js
CHANGED
|
@@ -39,8 +39,9 @@ import { metadataIdFromFile, defaultPageRoute } from './get-platform-files.task.
|
|
|
39
39
|
* (e.g. `/static/home.page-7f2a.js`).
|
|
40
40
|
*
|
|
41
41
|
* @typedef {object} Manifest
|
|
42
|
-
* @property {ManifestEntry[]} entries
|
|
43
|
-
* @property {object}
|
|
42
|
+
* @property {ManifestEntry[]} entries Flat, ordered list of every routable thing.
|
|
43
|
+
* @property {object[]} resourceTemplates Each `*.resource.js` file's default-exported template object.
|
|
44
|
+
* @property {object} config Inlined `src/config.js` default export.
|
|
44
45
|
*/
|
|
45
46
|
|
|
46
47
|
/**
|
|
@@ -83,7 +84,10 @@ export function manifestPlugin ({ entriesByStub, srcDir, staticOutDir, configVal
|
|
|
83
84
|
async writeBundle (_, bundle) {
|
|
84
85
|
/** @type {ManifestEntry[]} */
|
|
85
86
|
const entries = []
|
|
87
|
+
/** @type {object[]} */
|
|
88
|
+
const resourceTemplates = []
|
|
86
89
|
const seenIds = { page: new Set(), api: new Set(), task: new Set() }
|
|
90
|
+
const seenResourceIds = new Set()
|
|
87
91
|
|
|
88
92
|
for (const fileName of Object.keys(bundle)) {
|
|
89
93
|
const chunk = bundle[fileName]
|
|
@@ -109,6 +113,30 @@ export function manifestPlugin ({ entriesByStub, srcDir, staticOutDir, configVal
|
|
|
109
113
|
)
|
|
110
114
|
}
|
|
111
115
|
|
|
116
|
+
// Resources are pure data — the default export *is* the template.
|
|
117
|
+
// They don't use `metadata`, don't need a derived id, and don't
|
|
118
|
+
// produce a routable manifest entry; they accumulate into a separate
|
|
119
|
+
// `resourceTemplates` array on the manifest.
|
|
120
|
+
if (entryInfo.kind === 'resource') {
|
|
121
|
+
const template = mod && mod.default
|
|
122
|
+
if (!template || typeof template !== 'object' || Array.isArray(template)) {
|
|
123
|
+
this.error(
|
|
124
|
+
`[@ossy/app][build] resource entry ${entryInfo.sourcePath} must default-export an object`,
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
if (typeof template.id !== 'string' || template.id.trim() === '') {
|
|
128
|
+
this.error(
|
|
129
|
+
`[@ossy/app][build] resource entry ${entryInfo.sourcePath} default export is missing a non-empty string "id"`,
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
if (seenResourceIds.has(template.id)) {
|
|
133
|
+
this.error(`[@ossy/app][build] Duplicate resource template id "${template.id}"`)
|
|
134
|
+
}
|
|
135
|
+
seenResourceIds.add(template.id)
|
|
136
|
+
resourceTemplates.push(template)
|
|
137
|
+
continue
|
|
138
|
+
}
|
|
139
|
+
|
|
112
140
|
const rawMeta = (mod && mod.metadata) || {}
|
|
113
141
|
const id = rawMeta.id || metadataIdFromFile(entryInfo.sourcePath, srcDir)
|
|
114
142
|
if (!id) {
|
|
@@ -141,7 +169,7 @@ export function manifestPlugin ({ entriesByStub, srcDir, staticOutDir, configVal
|
|
|
141
169
|
}
|
|
142
170
|
|
|
143
171
|
/** @type {Manifest} */
|
|
144
|
-
const manifest = { entries, config: configValue || {} }
|
|
172
|
+
const manifest = { entries, resourceTemplates, config: configValue || {} }
|
|
145
173
|
fs.mkdirSync(path.dirname(manifestPath), { recursive: true })
|
|
146
174
|
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8')
|
|
147
175
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.7",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"build": "echo Building not required",
|
|
19
|
-
"test": "
|
|
19
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest --verbose",
|
|
20
20
|
"typecheck": "tsc --noEmit"
|
|
21
21
|
},
|
|
22
22
|
"keywords": [],
|
|
@@ -33,15 +33,15 @@
|
|
|
33
33
|
"@babel/eslint-parser": "^7.15.8",
|
|
34
34
|
"@babel/preset-react": "^7.26.3",
|
|
35
35
|
"@babel/register": "^7.25.9",
|
|
36
|
-
"@ossy/connected-components": "^1.16.
|
|
37
|
-
"@ossy/design-system": "^1.16.
|
|
38
|
-
"@ossy/pages": "^1.16.
|
|
39
|
-
"@ossy/platform": "^1.15.
|
|
40
|
-
"@ossy/router": "^1.16.
|
|
41
|
-
"@ossy/router-react": "^1.16.
|
|
42
|
-
"@ossy/sdk": "^1.16.
|
|
43
|
-
"@ossy/sdk-react": "^1.16.
|
|
44
|
-
"@ossy/themes": "^1.16.
|
|
36
|
+
"@ossy/connected-components": "^1.16.7",
|
|
37
|
+
"@ossy/design-system": "^1.16.7",
|
|
38
|
+
"@ossy/pages": "^1.16.7",
|
|
39
|
+
"@ossy/platform": "^1.15.7",
|
|
40
|
+
"@ossy/router": "^1.16.7",
|
|
41
|
+
"@ossy/router-react": "^1.16.7",
|
|
42
|
+
"@ossy/sdk": "^1.16.7",
|
|
43
|
+
"@ossy/sdk-react": "^1.16.7",
|
|
44
|
+
"@ossy/themes": "^1.16.7",
|
|
45
45
|
"@rollup/plugin-alias": "^6.0.0",
|
|
46
46
|
"@rollup/plugin-babel": "6.1.0",
|
|
47
47
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"README.md",
|
|
76
76
|
"tsconfig.json"
|
|
77
77
|
],
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "ca79da159a5d017ea80dfddbb7218b1a51aab396"
|
|
79
79
|
}
|