cayo 0.9.10 → 1.0.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/README.md +504 -5
- package/cayo.js +1 -298
- package/devlog.md +177 -0
- package/dist/cayo.svelte.js +80 -0
- package/dist/entry.svelte.js +16 -0
- package/dist/index.js +2 -0
- package/docs/config-reference.md +349 -0
- package/docs/how-cayo-works.md +28 -0
- package/docs/why-i-created-cayo.md +21 -0
- package/lib/cli/build.js +34 -0
- package/lib/cli/cli.js +152 -0
- package/lib/cli/dev.js +12 -0
- package/lib/cli/serve.js +25 -0
- package/lib/cli/watch.js +125 -0
- package/lib/core/bundle.js +155 -0
- package/lib/core/codegen.js +156 -0
- package/lib/core/compile/cayos.js +65 -0
- package/lib/core/compile/index.js +3 -0
- package/lib/core/compile/pages.js +61 -0
- package/lib/core/compile/template.js +24 -0
- package/lib/core/component.js +62 -0
- package/lib/core/config.js +206 -0
- package/lib/core/dependencies.js +167 -0
- package/lib/core/entry.js +24 -0
- package/lib/core/files.js +99 -0
- package/lib/core/logger.js +47 -0
- package/lib/core/page.js +59 -0
- package/lib/core/render/prerender.js +240 -0
- package/lib/core/render/renderer.js +52 -0
- package/lib/core/utils.js +60 -0
- package/package.json +21 -10
- package/scripts/build.js +60 -0
- package/src/cayo-warnings.js +37 -0
- package/src/cayo.svelte +36 -0
- package/src/entry.svelte +6 -0
- package/template/cayo.config.js +3 -0
- package/template/package-lock.json +4027 -0
- package/template/package.json +10 -0
- package/template/public/vite.svg +1 -0
- package/{tests/basic cases (old)/src/__index.svelte → template/src/__template.svelte} +3 -6
- package/template/src/components/counter.cayo.svelte +27 -0
- package/template/src/index.js +4 -0
- package/template/src/pages/index.svelte +15 -0
- package/template/src/style.css +13 -0
- package/lib/cli.js +0 -69
- package/lib/codegen.js +0 -79
- package/lib/components/Cayo.svelte +0 -25
- package/lib/config.js +0 -155
- package/lib/files.js +0 -84
- package/lib/prerender.js +0 -181
- package/lib/renderer.js +0 -49
- package/lib/runtime.js +0 -6
- package/lib/utils.js +0 -126
- package/lib/vite.config.js +0 -16
- package/notes.md +0 -3
- package/test/cayo.config.js +0 -35
- package/test/public/assets/cow.js +0 -1
- package/test/public/images/app-icon.png +0 -0
- package/test/src/__layout.svelte +0 -20
- package/test/src/components/Cool.cayo.svelte +0 -5
- package/test/src/components/Some.svelte +0 -1
- package/test/src/components/Test.cayo.svelte +0 -5
- package/test/src/index.js +0 -17
- package/test/src/main2.js +0 -1
- package/test/src/pages/hey.svelte +0 -8
- package/test/src/pages/howdy.svelte +0 -11
- package/test/src/pages/index.svelte +0 -38
- package/test/src/pages/some/page.svelte +0 -2
- package/tests/asset-dir/cayo.config.js +0 -38
- package/tests/asset-dir/package-lock.json +0 -1435
- package/tests/asset-dir/package.json +0 -19
- package/tests/asset-dir/public/images/app-icon.png +0 -0
- package/tests/asset-dir/src/__layout.svelte +0 -20
- package/tests/asset-dir/src/components/CayoExample.svelte +0 -5
- package/tests/asset-dir/src/components/Some.cayo.svelte +0 -6
- package/tests/asset-dir/src/index.js +0 -5
- package/tests/asset-dir/src/pages/index.svelte +0 -19
- package/tests/base-path/cayo.config.js +0 -36
- package/tests/base-path/package-lock.json +0 -1435
- package/tests/base-path/package.json +0 -19
- package/tests/base-path/public/assets/cow.js +0 -1
- package/tests/base-path/public/images/app-icon.png +0 -0
- package/tests/base-path/src/__layout.svelte +0 -20
- package/tests/base-path/src/components/CayoExample.svelte +0 -5
- package/tests/base-path/src/components/Some.cayo.svelte +0 -6
- package/tests/base-path/src/index.js +0 -5
- package/tests/base-path/src/pages/howdy.svelte +0 -12
- package/tests/base-path/src/pages/index.svelte +0 -20
- package/tests/basic/notcayo.config.js +0 -35
- package/tests/basic/package-lock.json +0 -1435
- package/tests/basic/package.json +0 -19
- package/tests/basic/public/assets/cow.js +0 -1
- package/tests/basic/public/images/app-icon.png +0 -0
- package/tests/basic/src/__layout.svelte +0 -20
- package/tests/basic/src/components/Cool.cayo.svelte +0 -4
- package/tests/basic/src/components/Some.svelte +0 -1
- package/tests/basic/src/index.js +0 -5
- package/tests/basic/src/main2.js +0 -1
- package/tests/basic/src/pages/hey.svelte +0 -8
- package/tests/basic/src/pages/howdy.svelte +0 -11
- package/tests/basic/src/pages/index.svelte +0 -33
- package/tests/basic/src/pages/some/some.svelte +0 -2
- package/tests/basic cases (old)/src/components/Cool.cayo.svelte +0 -4
- package/tests/basic cases (old)/src/components/Some.svelte +0 -1
- package/tests/basic cases (old)/src/components/dir/Cool.cayo.svelte +0 -4
- package/tests/basic cases (old)/src/main.js +0 -1
- package/tests/basic cases (old)/src/main2.js +0 -1
- package/tests/basic cases (old)/src/pages/hey.svelte +0 -2
- package/tests/basic cases (old)/src/pages/howdy.svelte +0 -11
- package/tests/basic cases (old)/src/pages/index.svelte +0 -27
- package/tests/nested-pages/cayo.config.js +0 -35
- package/tests/nested-pages/package-lock.json +0 -1435
- package/tests/nested-pages/package.json +0 -19
- package/tests/nested-pages/public/assets/cow.js +0 -1
- package/tests/nested-pages/public/images/app-icon.png +0 -0
- package/tests/nested-pages/src/__layout.svelte +0 -20
- package/tests/nested-pages/src/components/Cool.cayo.svelte +0 -4
- package/tests/nested-pages/src/index.js +0 -5
- package/tests/nested-pages/src/main2.js +0 -1
- package/tests/nested-pages/src/pages/index.svelte +0 -18
- package/tests/nested-pages/src/pages/some/other/page.svelte +0 -7
- package/tests/nested-pages/src/pages/some/page.svelte +0 -6
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import merge from 'deepmerge';
|
|
5
|
+
import { defineConfig } from 'vite';
|
|
6
|
+
import { normalizePath } from './utils.js';
|
|
7
|
+
|
|
8
|
+
export async function validateConfig(userConfig) {
|
|
9
|
+
const ConfigSchema = z.object({
|
|
10
|
+
projectRoot: z
|
|
11
|
+
.string()
|
|
12
|
+
.default('.'),
|
|
13
|
+
src: z
|
|
14
|
+
.string()
|
|
15
|
+
.default('./src'),
|
|
16
|
+
pages: z
|
|
17
|
+
.string()
|
|
18
|
+
.default('./pages'),
|
|
19
|
+
components: z
|
|
20
|
+
.string()
|
|
21
|
+
.default('./components'),
|
|
22
|
+
publicDir: z
|
|
23
|
+
.string()
|
|
24
|
+
.default('./public'),
|
|
25
|
+
// TODO: make this an object with `value` and `mode` so it can be toggled per env if needed
|
|
26
|
+
base: z
|
|
27
|
+
.string()
|
|
28
|
+
.default('/'),
|
|
29
|
+
build: z
|
|
30
|
+
.object({
|
|
31
|
+
outDir: z
|
|
32
|
+
.string()
|
|
33
|
+
.default('./dist'),
|
|
34
|
+
assetsDir: z
|
|
35
|
+
.string()
|
|
36
|
+
.default('assets'),
|
|
37
|
+
})
|
|
38
|
+
.optional()
|
|
39
|
+
.default({}),
|
|
40
|
+
css: z
|
|
41
|
+
.object({
|
|
42
|
+
internal: z
|
|
43
|
+
.boolean()
|
|
44
|
+
.default(false),
|
|
45
|
+
})
|
|
46
|
+
.optional()
|
|
47
|
+
.default({}),
|
|
48
|
+
// Note: explicitly only supports these svelte config options
|
|
49
|
+
svelte: z.object({
|
|
50
|
+
preprocess: z.any().default([]),
|
|
51
|
+
compilerOptions: z.any().default({}),
|
|
52
|
+
extensions: z.string().array().default(['.svelte']),
|
|
53
|
+
}).default({}),
|
|
54
|
+
// Note: allows all vite config options
|
|
55
|
+
vite: z.any({}).default({
|
|
56
|
+
clearScreen: false,
|
|
57
|
+
rollupOptions: {
|
|
58
|
+
plugins: [],
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
cayoPath: z
|
|
62
|
+
.string()
|
|
63
|
+
.default('.cayo/'),
|
|
64
|
+
cayoComponentInfix: z
|
|
65
|
+
.string()
|
|
66
|
+
.default('cayo'),
|
|
67
|
+
templateName: z
|
|
68
|
+
.string()
|
|
69
|
+
.default('__template'),
|
|
70
|
+
//TODO: make sure this matches the config docs
|
|
71
|
+
mode: z
|
|
72
|
+
.string()
|
|
73
|
+
.default('development'),
|
|
74
|
+
debug: z
|
|
75
|
+
.boolean()
|
|
76
|
+
.default(false),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return await ConfigSchema.strict().parseAsync(userConfig);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function handlePaths(config, input, base) {
|
|
83
|
+
// Build paths from the config options
|
|
84
|
+
let projectRoot = normalizePath(base, config.projectRoot);
|
|
85
|
+
let src = normalizePath(projectRoot, config.src);
|
|
86
|
+
let pages = normalizePath(src, config.pages);
|
|
87
|
+
let components = normalizePath(src, config.components);
|
|
88
|
+
let publicDir = normalizePath(projectRoot, config.publicDir);
|
|
89
|
+
let build = {
|
|
90
|
+
outDir: normalizePath(projectRoot, config.build.outDir),
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
// Handle the template path a little differently below, since the option is a name not a path
|
|
95
|
+
let templateName = config.templateName;
|
|
96
|
+
let templatePath = path.join(src, `${templateName}.svelte`);
|
|
97
|
+
|
|
98
|
+
// Validate the built paths
|
|
99
|
+
let errorMessage = '';
|
|
100
|
+
let isError = false;
|
|
101
|
+
let isInvalidInput = false;
|
|
102
|
+
const pathsToCheck = { projectRoot, src, pages, components, templatePath, publicDir };
|
|
103
|
+
const exists = async (key, value) => {
|
|
104
|
+
if (!(await fs.pathExists(value))) {
|
|
105
|
+
if (!input[key] && key !== 'templatePath') {
|
|
106
|
+
errorMessage += `\n\n> Expected '${key}' path does not exist: ${value}`;
|
|
107
|
+
} else {
|
|
108
|
+
switch(key) {
|
|
109
|
+
case 'templatePath':
|
|
110
|
+
errorMessage += `\n\n> 'templateName': ${templateName} (.svelte) not found at root of 'src' path.`;
|
|
111
|
+
errorMessage += `\n Expected template path does not exist: ${templatePath}`;
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
errorMessage += `\n\n> ${key}: realtive path does not exist: ${input[key]}`
|
|
115
|
+
errorMessage += `\n Expected '${key}' path does not exist: ${value}`;
|
|
116
|
+
isInvalidInput = true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
isError = true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (const [key, value] of Object.entries(pathsToCheck)) {
|
|
123
|
+
exists(key, value);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!isError) {
|
|
127
|
+
// Update the config to use the validated absolute path values
|
|
128
|
+
config.projectRoot = projectRoot;
|
|
129
|
+
config.src = src;
|
|
130
|
+
config.pages = pages;
|
|
131
|
+
config.components = components;
|
|
132
|
+
config.template = templatePath;
|
|
133
|
+
config.publicDir = publicDir;
|
|
134
|
+
config.build.outDir = build.outDir;
|
|
135
|
+
|
|
136
|
+
} else {
|
|
137
|
+
if (isInvalidInput) errorMessage = 'Config includes an invalid path.' + errorMessage;
|
|
138
|
+
else errorMessage = `Project structure is invalid.` + errorMessage;
|
|
139
|
+
throw new Error(errorMessage);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function handleZodError(error) {
|
|
144
|
+
let msg = 'Config is invalid.';
|
|
145
|
+
for (const e of error.issues) {
|
|
146
|
+
msg += `\n\n> ${e.message}`;
|
|
147
|
+
}
|
|
148
|
+
throw new Error(msg);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export async function loadConfig(options) {
|
|
152
|
+
const configFileName = 'cayo.config.js';
|
|
153
|
+
|
|
154
|
+
// Use command-line options if user passes them
|
|
155
|
+
const root = options.projectRoot
|
|
156
|
+
? path.resolve(options.projectRoot)
|
|
157
|
+
: process.cwd();
|
|
158
|
+
|
|
159
|
+
const configPath = options.configPath
|
|
160
|
+
? path.resolve(root, options.configPath)
|
|
161
|
+
: path.resolve(root, `./${configFileName}`);
|
|
162
|
+
|
|
163
|
+
// Load config from user config file
|
|
164
|
+
let userConfig = { projectRoot: root, mode: options.mode };
|
|
165
|
+
if (fs.existsSync(configPath)) {
|
|
166
|
+
userConfig = {
|
|
167
|
+
...(await import(configPath)).default,
|
|
168
|
+
...userConfig,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let config = null;
|
|
173
|
+
try {
|
|
174
|
+
config = await validateConfig(userConfig);
|
|
175
|
+
await handlePaths(config, userConfig, root);
|
|
176
|
+
} catch (err) {
|
|
177
|
+
if (err instanceof z.ZodError) {
|
|
178
|
+
throw handleZodError(err);
|
|
179
|
+
}
|
|
180
|
+
throw err;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (config && config.vite) {
|
|
184
|
+
const mergedViteConfig = merge(defineConfig({}), config.vite, { arrayMerge: combineMerge });
|
|
185
|
+
config.vite = mergedViteConfig;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return config;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Credit: https://github.com/TehShrike/deepmerge#arraymerge-example-combine-arrays
|
|
192
|
+
function combineMerge(target, source, options) {
|
|
193
|
+
const destination = target.slice();
|
|
194
|
+
|
|
195
|
+
source.forEach((item, index) => {
|
|
196
|
+
if (typeof destination[index] === 'undefined') {
|
|
197
|
+
destination[index] = options.cloneUnlessOtherwiseSpecified(item, options);
|
|
198
|
+
} else if (options.isMergeableObject(item)) {
|
|
199
|
+
destination[index] = merge(target[index], item, options);
|
|
200
|
+
} else if (target.indexOf(item) === -1) {
|
|
201
|
+
destination.push(item);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
return destination;
|
|
206
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import precinct from 'precinct';
|
|
3
|
+
import { getDeps } from './bundle.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Adds dependencies to the dependency tree
|
|
7
|
+
*
|
|
8
|
+
* @param {object} depender – a dependency branch (for a page or child component)
|
|
9
|
+
* @param {object} dependencies – the dependency tree
|
|
10
|
+
*/
|
|
11
|
+
function addDependencies(depender, dependencies) {
|
|
12
|
+
let type;
|
|
13
|
+
let branch = [...depender.dependencies];
|
|
14
|
+
|
|
15
|
+
// Update existing branches with these new deps where applicable
|
|
16
|
+
for (const [key, page] of Object.entries(dependencies.pages)) {
|
|
17
|
+
for (const component of dependencies.pages[key]) {
|
|
18
|
+
if (depender.path === component && dependencies.components[component]) {
|
|
19
|
+
dependencies.pages[key] = new Set([
|
|
20
|
+
...dependencies.pages[key],
|
|
21
|
+
...dependencies.components[component]
|
|
22
|
+
]);
|
|
23
|
+
depender.dependencies = [...dependencies.pages[key]];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
switch (depender.type) {
|
|
29
|
+
case 'page':
|
|
30
|
+
type = 'pages';
|
|
31
|
+
break;
|
|
32
|
+
case 'component':
|
|
33
|
+
type = 'components';
|
|
34
|
+
break;
|
|
35
|
+
case 'entry':
|
|
36
|
+
type = 'entries';
|
|
37
|
+
break;
|
|
38
|
+
case 'asset':
|
|
39
|
+
default:
|
|
40
|
+
type = 'assets';
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
dependencies[type][depender.path] = new Set([...branch]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Recursively handles component deps,
|
|
49
|
+
* updates the depedendency tree,
|
|
50
|
+
* and updates the list of compiled components
|
|
51
|
+
*
|
|
52
|
+
* @param {object} depender a dependency branch (for a page or child component)
|
|
53
|
+
* @param {object} stats information about all dependers, their dependencies,
|
|
54
|
+
* and what components have been compiled this run
|
|
55
|
+
* @param {object} config cayo config
|
|
56
|
+
*/
|
|
57
|
+
export async function handleDependencies(depender, _cayo) {
|
|
58
|
+
const { stats, config } = _cayo;
|
|
59
|
+
|
|
60
|
+
// Add the depender to the dependency tree
|
|
61
|
+
const branch = addDependencies(depender, stats.dependencies);
|
|
62
|
+
// Add the depender to the list of compiled dependencies
|
|
63
|
+
stats.compiled.paths.add(depender.path);
|
|
64
|
+
|
|
65
|
+
// Iterate over the dependency tree
|
|
66
|
+
for (const dependency of depender.dependencies) {
|
|
67
|
+
let type;
|
|
68
|
+
if (dependency.endsWith('.svelte')) {
|
|
69
|
+
type = 'component';
|
|
70
|
+
} else if (dependency.endsWith('.js')) {
|
|
71
|
+
type = 'asset';
|
|
72
|
+
} else {
|
|
73
|
+
// Return early if it's not a file we can handle
|
|
74
|
+
return branch;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!stats.compiled.paths.has(dependency)) {
|
|
78
|
+
const deps = (await getDeps(dependency, config));
|
|
79
|
+
// Recursively handle nested dependencies
|
|
80
|
+
if (deps) {
|
|
81
|
+
await handleDependencies({
|
|
82
|
+
type,
|
|
83
|
+
path: dependency,
|
|
84
|
+
dependencies: deps
|
|
85
|
+
}, _cayo, config);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return branch;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function findDependentPages(dependency, _cayo) {
|
|
94
|
+
const { components, pages } = _cayo.stats.dependencies;
|
|
95
|
+
const dependentComponents = new Set([dependency]);
|
|
96
|
+
const dependentPages = new Set();
|
|
97
|
+
|
|
98
|
+
// Lookup dependency in other components
|
|
99
|
+
for (const [depender, deps] of Object.entries(components)) {
|
|
100
|
+
if (deps.has(dependency)) {
|
|
101
|
+
dependentComponents.add(depender);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Lookup any dependent components in pages
|
|
106
|
+
for (const [depender, deps] of Object.entries(pages)) {
|
|
107
|
+
for (const component of dependentComponents) {
|
|
108
|
+
if (deps.has(component)) {
|
|
109
|
+
dependentPages.add(depender)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return dependentPages;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function findDependentCayos(pageDependency, _cayo) {
|
|
118
|
+
const { components, pages } = _cayo.stats.dependencies;
|
|
119
|
+
const dependentComponents = new Set([]);
|
|
120
|
+
const cayos = new Set([]);
|
|
121
|
+
|
|
122
|
+
// Lookup dependency in the page
|
|
123
|
+
for (const dep of pages[pageDependency]) {
|
|
124
|
+
if (dep.endsWith('.cayo.svelte')) cayos.add(dep);
|
|
125
|
+
else if (dep.endsWith('.svelte')) dependentComponents.add(dep);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Lookup dependency in components that the page is dependent on
|
|
129
|
+
for (const component of dependentComponents) {
|
|
130
|
+
for (const dep of components[component]) {
|
|
131
|
+
if (dep.endsWith('.cayo.svelte')) {
|
|
132
|
+
cayos.add(dep);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return cayos;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function getEntryDependencies(entry, page, _cayo) {
|
|
141
|
+
const { config } = _cayo;
|
|
142
|
+
let imports = precinct(entry.code, { type: 'es6' });
|
|
143
|
+
// Filter out public path ('/') and node_modules ('<package>')
|
|
144
|
+
let localDeps = imports.filter(d => d.startsWith('../') || d.startsWith('./'));
|
|
145
|
+
let absoluteDeps = localDeps.map(d => path.resolve(path.dirname(entry.path), d));
|
|
146
|
+
let srcRelativeLocalDeps = localDeps.map((d, i) => {
|
|
147
|
+
let pageCayoPath = path.resolve(config.cayoPath, page.url === '/' ? './' : page.url);
|
|
148
|
+
return path.relative(pageCayoPath, absoluteDeps[i]);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
entry.dependencies = [];
|
|
152
|
+
for (let i = 0; i < localDeps.length; i++) {
|
|
153
|
+
entry.dependencies.push([localDeps[i], srcRelativeLocalDeps[i]]);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const depender = {
|
|
157
|
+
type: 'entry',
|
|
158
|
+
path: entry.path,
|
|
159
|
+
dependencies: absoluteDeps,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
await handleDependencies(depender, _cayo);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
throw new Error(`Parsing dependencies of entry file '${entry.path}'`, { cause: err })
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import { getEntryDependencies } from './dependencies.js';
|
|
3
|
+
import { generateCayoRuntimeImport } from './codegen.js';
|
|
4
|
+
|
|
5
|
+
export async function processEntrySource(entry, page, _cayo) {
|
|
6
|
+
try {
|
|
7
|
+
entry.code = await fs.readFile(entry.path, { encoding: 'utf8' });
|
|
8
|
+
} catch (err) {
|
|
9
|
+
throw err;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let code = `${entry.code}`;
|
|
13
|
+
// Rewrite dependency imports
|
|
14
|
+
await getEntryDependencies(entry, page, _cayo);
|
|
15
|
+
for (const [relativeDep, srcRelativeDep] of entry.dependencies) {
|
|
16
|
+
code = code.replace(relativeDep, srcRelativeDep);
|
|
17
|
+
}
|
|
18
|
+
// Prepend cayo runtime import to entry source code
|
|
19
|
+
if (entry.renderCayos) {
|
|
20
|
+
code = generateCayoRuntimeImport() + code;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return code;
|
|
24
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { processEntrySource } from './entry.js';
|
|
5
|
+
import prettier from 'prettier';
|
|
6
|
+
// import logger from './logger.js';
|
|
7
|
+
|
|
8
|
+
const logger = {
|
|
9
|
+
log: {
|
|
10
|
+
info: () => {}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Write file content for a page
|
|
15
|
+
export async function writePageFiles(page, _cayo) {
|
|
16
|
+
const { config } = _cayo;
|
|
17
|
+
const outDir = config.cayoPath;
|
|
18
|
+
const { html, css, js, cayoAssets } = page.result;
|
|
19
|
+
const htmlPath = page.url === '/' ? 'index.html' : `${page.url}/index.html`;
|
|
20
|
+
const prettyHtml = prettier.format(html, { parser: 'html'})
|
|
21
|
+
|
|
22
|
+
// Write HTML
|
|
23
|
+
await fs.outputFile(path.resolve(outDir, `${htmlPath}`), prettyHtml)
|
|
24
|
+
.then(() => logger.log.info(
|
|
25
|
+
chalk.green('page build ') + chalk.dim(`${page.name}`),
|
|
26
|
+
{ timestamp: true })
|
|
27
|
+
);
|
|
28
|
+
// Write CSS
|
|
29
|
+
if (css.code !== '' && !config.css.internal) {
|
|
30
|
+
const cssPath = page.url === '/' ? 'index.css' : `${page.url}/index.css`;
|
|
31
|
+
await fs.outputFile(path.resolve(outDir, cssPath), css)
|
|
32
|
+
.then(() => logger.log.info(
|
|
33
|
+
chalk.green('css build ') + chalk.dim(`${page.name}`),
|
|
34
|
+
{ timestamp: true })
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
// Write Cayo runtime JS
|
|
38
|
+
if (js.code !== '') {
|
|
39
|
+
let jsPath = page.url === '/' ? 'cayo-runtime.js' : `${page.url}/cayo-runtime.js`;
|
|
40
|
+
let content = '';
|
|
41
|
+
content += js.code;
|
|
42
|
+
await fs.outputFile(path.resolve(outDir, jsPath), content)
|
|
43
|
+
.then(() => logger.log.info(
|
|
44
|
+
chalk.green('cayo runtime build ') + chalk.dim(`${page.name}`),
|
|
45
|
+
{ timestamp: true })
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
// Write Cayo CSS
|
|
49
|
+
for (const [name, cayo] of Object.entries(cayoAssets)) {
|
|
50
|
+
if (cayo.css.code !== '' && !config.css.internal) {
|
|
51
|
+
const cssPath = `${name}.css`;
|
|
52
|
+
await fs.outputFile(path.resolve(outDir, cssPath), cayo.css.code)
|
|
53
|
+
.then(() => logger.log.info(
|
|
54
|
+
chalk.green('css build ') + chalk.dim(`${cssPath}`),
|
|
55
|
+
{ timestamp: true })
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
await writeEntryFile(page, _cayo);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function writeEntryFile(page, _cayo) {
|
|
64
|
+
const { config } = _cayo;
|
|
65
|
+
const { entry } = page.result;
|
|
66
|
+
|
|
67
|
+
if (entry.path) {
|
|
68
|
+
// Get the processed entry code
|
|
69
|
+
// TODO: should this happen here?
|
|
70
|
+
let code = await processEntrySource(entry, page, _cayo);
|
|
71
|
+
// Write the processed entry file
|
|
72
|
+
let entryOutputPath = page.url === '/' ? `./index.js` : `${page.url}/index.js`;
|
|
73
|
+
await fs.outputFile(path.resolve(config.cayoPath, entryOutputPath), code)
|
|
74
|
+
.then(() => logger.log.info(
|
|
75
|
+
chalk.green('entry build ') + chalk.dim(`${page.name}`),
|
|
76
|
+
{ timestamp: true }
|
|
77
|
+
))
|
|
78
|
+
.catch(err => console.error(err));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function writeTemplateCSS(css, _cayo) {
|
|
83
|
+
const { config } = _cayo;
|
|
84
|
+
const outDir = config.cayoPath;
|
|
85
|
+
|
|
86
|
+
if (css.code !== '' && !config.css.internal) {
|
|
87
|
+
const cssPath = `__index.css`;
|
|
88
|
+
await fs.outputFile(path.resolve(outDir, cssPath), css.code)
|
|
89
|
+
.then(() => logger.log.info(
|
|
90
|
+
chalk.green('css build ') + chalk.dim(`${config.templateFileName}`),
|
|
91
|
+
{ timestamp: true })
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function cleanCayoPath(cayoPath) {
|
|
97
|
+
fs.removeSync(cayoPath);
|
|
98
|
+
fs.ensureDirSync(cayoPath);
|
|
99
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createLogger } from 'vite';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export const infoLogger = createLogger('info', {
|
|
5
|
+
prefix: chalk.magenta.bold('[cayo]'),
|
|
6
|
+
// allowClearScreen: true,
|
|
7
|
+
});
|
|
8
|
+
export const errorLoggerVite = createLogger('error', {
|
|
9
|
+
prefix: chalk.red.bold('[cayo]'),
|
|
10
|
+
// allowClearScreen: true,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const errorLogger = (err) => {
|
|
14
|
+
let errorMessage = err;
|
|
15
|
+
// TODO: good reason to write a new logger that is
|
|
16
|
+
// globally initialized and passed in a runtime object,
|
|
17
|
+
// so this could have access to _cayo.config options
|
|
18
|
+
// Only really useful for dev
|
|
19
|
+
// if (err.stack) errorMessage = err.stack;
|
|
20
|
+
console.error(chalk.red.bold(`${errorMessage}`));
|
|
21
|
+
|
|
22
|
+
if (err.cause && !err.cause.cause) {
|
|
23
|
+
console.error(`${chalk.red.bold('> Cause:')} ${chalk.red.bold(err.cause)}`);
|
|
24
|
+
// console.error(err.cause.stack);
|
|
25
|
+
} else {
|
|
26
|
+
handleCause(err);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const handleCause = (err) => {
|
|
31
|
+
let prefix = chalk.red.bold('> Cause:');
|
|
32
|
+
if (err.cause) {
|
|
33
|
+
console.error(`${prefix} ${chalk.red.bold(err.cause)}`);
|
|
34
|
+
// console.error(err.cause.stack);
|
|
35
|
+
handleCause(err.cause);
|
|
36
|
+
} else {
|
|
37
|
+
// console.error(`${prefix} ${chalk.red.bold(err.stack)}`);
|
|
38
|
+
// console.error(err.stack);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const logger = {
|
|
43
|
+
log: infoLogger,
|
|
44
|
+
error: errorLogger,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default logger;
|
package/lib/core/page.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Component } from "./component.js";
|
|
2
|
+
import { prerender } from "./render/prerender.js";
|
|
3
|
+
|
|
4
|
+
export class Page extends Component {
|
|
5
|
+
constructor(
|
|
6
|
+
code,
|
|
7
|
+
layout,
|
|
8
|
+
sourcePath,
|
|
9
|
+
modulePath,
|
|
10
|
+
dependencies,
|
|
11
|
+
config
|
|
12
|
+
) {
|
|
13
|
+
super(null, code, sourcePath, modulePath, dependencies, config);
|
|
14
|
+
this._url = sourcePath.replace(config.pages, '').replace('.svelte', '');
|
|
15
|
+
this._name = sourcePath.split('/').pop().replace('.svelte', '');
|
|
16
|
+
this._modulePath = modulePath;
|
|
17
|
+
this._sourcePath = sourcePath;
|
|
18
|
+
this._layout = layout;
|
|
19
|
+
this._result;
|
|
20
|
+
this._cayoComponents = {};
|
|
21
|
+
|
|
22
|
+
if (this._url === 'index') this._url = '/';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async render(_cayo, options = {}) {
|
|
26
|
+
const { load = false } = options;
|
|
27
|
+
if (load) await this.load();
|
|
28
|
+
try {
|
|
29
|
+
this._result = await prerender(
|
|
30
|
+
this,
|
|
31
|
+
_cayo,
|
|
32
|
+
);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
throw new Error(`Could not prerender page '${this._name}'`, { cause: err })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get layout() {
|
|
41
|
+
return this._layout;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get url() {
|
|
45
|
+
return this._url;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get result() {
|
|
49
|
+
return this._result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get sourcePath() {
|
|
53
|
+
return this._sourcePath;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
addCayoComponents(name, cayo) {
|
|
57
|
+
this._cayoComponents[name] = cayo;
|
|
58
|
+
}
|
|
59
|
+
}
|