@geastack/core 0.1.41 → 0.1.43
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 +36 -9
- package/events.cpp +11 -0
- package/gea_app_entry.cpp +4 -0
- package/gea_sources.mjs +12 -2
- package/gea_sources.sh +6 -1
- package/include/canvas.h +1 -0
- package/include/display.h +1 -0
- package/include/event_listener_options.h +26 -0
- package/include/events.h +109 -5
- package/include/gea/embedded.h +1 -0
- package/include/graphics/font.h +11 -0
- package/include/native_identity.h +65 -0
- package/include/platform/asset_bundle.h +71 -0
- package/include/platform/esp_now.h +113 -0
- package/include/platform/magnetometer.h +60 -0
- package/include/platform/uart.h +58 -0
- package/include/runtime.h +14 -0
- package/index.d.ts +183 -8
- package/package.json +5 -2
- package/runtime/host.ts +95 -0
- package/runtime-surface.ts +7 -0
- package/runtime.cpp +145 -16
- package/scripts/build-gea-vite-geatsc.mjs +27 -3
- package/scripts/gea-file-asset-bundle.mjs +82 -0
- package/scripts/gea-native-style-plugin.mjs +3 -1
- package/scripts/gea-vite-plugin-resolution.mjs +49 -0
- package/scripts/generate-gea-embedded-assets.mjs +20 -3
- package/scripts/generate-gea-embedded-fonts.mjs +25 -4
- package/scripts/tests/gea-vite-plugin-resolution.test.mjs +46 -0
|
@@ -11,6 +11,7 @@ import { execFileSync } from "node:child_process";
|
|
|
11
11
|
import { createHash } from "node:crypto";
|
|
12
12
|
import { createRequire } from "node:module";
|
|
13
13
|
import { fileURLToPath } from "node:url";
|
|
14
|
+
import { fileAssetBundle, fileAssetLoader } from "./gea-file-asset-bundle.mjs";
|
|
14
15
|
|
|
15
16
|
const args = process.argv.slice(2);
|
|
16
17
|
|
|
@@ -1060,6 +1061,7 @@ function generatedCpp(fonts, families) {
|
|
|
1060
1061
|
// this TU too (a weak symbol can't be defined twice in one TU); `font_data`
|
|
1061
1062
|
// points at the shared symbol either way.
|
|
1062
1063
|
const atlasSymbols = new Map();
|
|
1064
|
+
const atlasEntries = [];
|
|
1063
1065
|
for (const font of fonts) {
|
|
1064
1066
|
const hash = createHash("sha1")
|
|
1065
1067
|
.update(Buffer.from(font.atlasData))
|
|
@@ -1069,14 +1071,23 @@ function generatedCpp(fonts, families) {
|
|
|
1069
1071
|
font.atlasSymbol = symbol;
|
|
1070
1072
|
if (atlasSymbols.has(hash)) continue;
|
|
1071
1073
|
atlasSymbols.set(hash, symbol);
|
|
1074
|
+
atlasEntries.push({ symbol, data: font.atlasData });
|
|
1075
|
+
}
|
|
1076
|
+
const bundle = fileAssetBundle(appDir, outCpp, 'fonts', atlasEntries);
|
|
1077
|
+
if (bundle) lines.unshift('#include "platform/asset_bundle.h"');
|
|
1078
|
+
for (const { symbol, data } of atlasEntries) {
|
|
1079
|
+
if (bundle) {
|
|
1080
|
+
lines.push(`__attribute__((weak)) GEA_FILE_ASSET_BUFFER std::uint8_t ${symbol}[${Math.max(1, data.length)}];`);
|
|
1081
|
+
continue;
|
|
1082
|
+
}
|
|
1072
1083
|
// `extern` + initializer: a namespace-scope `const` is internal by default,
|
|
1073
1084
|
// and `weak` requires external linkage ("weak declaration must be public").
|
|
1074
1085
|
lines.push(
|
|
1075
|
-
`extern __attribute__((weak)) const std::uint8_t ${symbol}[${
|
|
1086
|
+
`extern __attribute__((weak)) const std::uint8_t ${symbol}[${data.length}] = {`,
|
|
1076
1087
|
);
|
|
1077
|
-
for (let i = 0; i <
|
|
1088
|
+
for (let i = 0; i < data.length; i += 32) {
|
|
1078
1089
|
const chunk = Array.from(
|
|
1079
|
-
|
|
1090
|
+
data.slice(i, Math.min(i + 32, data.length)),
|
|
1080
1091
|
);
|
|
1081
1092
|
lines.push(
|
|
1082
1093
|
` ${chunk.map((byte) => `0x${byte.toString(16).padStart(2, "0")}`).join(", ")},`,
|
|
@@ -1085,6 +1096,7 @@ function generatedCpp(fonts, families) {
|
|
|
1085
1096
|
lines.push("};");
|
|
1086
1097
|
lines.push("");
|
|
1087
1098
|
}
|
|
1099
|
+
if (bundle) lines.push(...fileAssetLoader(bundle, 'prepareFontAssets'));
|
|
1088
1100
|
|
|
1089
1101
|
for (const font of fonts) {
|
|
1090
1102
|
// `atlasBits` defaults to 8 in RasterizedFontData, so an 8-bit atlas leaves
|
|
@@ -1144,12 +1156,14 @@ function generatedCpp(fonts, families) {
|
|
|
1144
1156
|
lines.push("");
|
|
1145
1157
|
lines.push(`void ${names.ensureLinked}()`);
|
|
1146
1158
|
lines.push("{");
|
|
1159
|
+
if (bundle) lines.push(' (void)prepareFontAssets();');
|
|
1147
1160
|
lines.push("}");
|
|
1148
1161
|
lines.push("");
|
|
1149
1162
|
lines.push(
|
|
1150
1163
|
`const gea::framework::graphics::RasterizedFontData *${names.lookupFont}(int fontId)`,
|
|
1151
1164
|
);
|
|
1152
1165
|
lines.push("{");
|
|
1166
|
+
if (bundle) lines.push(' if (!prepareFontAssets()) return nullptr;');
|
|
1153
1167
|
lines.push(" for (const auto &entry : generated_fonts) {");
|
|
1154
1168
|
lines.push(
|
|
1155
1169
|
" if (entry.font && entry.font->id == fontId) return entry.font;",
|
|
@@ -1162,6 +1176,7 @@ function generatedCpp(fonts, families) {
|
|
|
1162
1176
|
`const gea::framework::graphics::RasterizedFontData *${names.lookupFontForFamily}(int familyId, int sizePx)`,
|
|
1163
1177
|
);
|
|
1164
1178
|
lines.push("{");
|
|
1179
|
+
if (bundle) lines.push(' if (!prepareFontAssets()) return nullptr;');
|
|
1165
1180
|
lines.push(" const RasterizedFontData *best = nullptr;");
|
|
1166
1181
|
lines.push(" int bestDiff = 2147483647;");
|
|
1167
1182
|
lines.push(" for (const auto &entry : generated_fonts) {");
|
|
@@ -1510,7 +1525,13 @@ function writeFileIfChanged(filePath, contents) {
|
|
|
1510
1525
|
function writeGeneratedFonts() {
|
|
1511
1526
|
const fontFaces = collectSourceFontFaces();
|
|
1512
1527
|
const tuples = collectUsedFontTuples(fontFaces);
|
|
1513
|
-
|
|
1528
|
+
// Runtime fonts are selected at actual layout time, including CSS variables
|
|
1529
|
+
// and programmatic styles with no statically discoverable family/size tuple.
|
|
1530
|
+
// Keep every explicitly declared local face; raster-only builds retain their
|
|
1531
|
+
// existing tuple-pruned size/charset policy.
|
|
1532
|
+
const familyNames = runtimeTtfFonts
|
|
1533
|
+
? [...fontFaces.keys()].sort()
|
|
1534
|
+
: [...new Set(tuples.map((tuple) => tuple.family))].sort();
|
|
1514
1535
|
const families = familyNames.map((name, id) => ({ id, name }));
|
|
1515
1536
|
const familyIds = new Map(families.map((family) => [family.name, family.id]));
|
|
1516
1537
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import test from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import os from 'node:os'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
import { resolveAppGeaVitePlugin } from '../gea-vite-plugin-resolution.mjs'
|
|
7
|
+
|
|
8
|
+
test('declared app plugin honors its real package/version and symlink; undeclared alone inherits Core', () => {
|
|
9
|
+
const root = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'gea-plugin-resolution-')))
|
|
10
|
+
try {
|
|
11
|
+
const app = path.join(root,'app'), core = path.join(root,'core')
|
|
12
|
+
for (const p of [app,core]) { fs.mkdirSync(p); fs.writeFileSync(path.join(p,'package.json'),'{}') }
|
|
13
|
+
const install = (parent, version) => {
|
|
14
|
+
const pkg=path.join(parent,'node_modules/@geajs/vite-plugin'); fs.mkdirSync(pkg,{recursive:true})
|
|
15
|
+
fs.writeFileSync(path.join(pkg,'package.json'),JSON.stringify({name:'@geajs/vite-plugin',version,type:'module',exports:{'.':{import:'./index.mjs'}}}))
|
|
16
|
+
fs.writeFileSync(path.join(pkg,'index.mjs'),`export const version=${JSON.stringify(version)}`)
|
|
17
|
+
return pkg
|
|
18
|
+
}
|
|
19
|
+
const legacy=install(core,'1.4.1')
|
|
20
|
+
assert.equal(resolveAppGeaVitePlugin(app,path.join(core,'package.json')),path.join(legacy,'index.mjs'))
|
|
21
|
+
fs.writeFileSync(path.join(app,'package.json'),JSON.stringify({devDependencies:{'@geajs/vite-plugin':'file:../source'}}))
|
|
22
|
+
assert.throws(()=>resolveAppGeaVitePlugin(app,path.join(core,'package.json')),/App declares/)
|
|
23
|
+
const source=install(root,'1.5.0')
|
|
24
|
+
fs.mkdirSync(path.join(app,'node_modules/@geajs'),{recursive:true})
|
|
25
|
+
fs.symlinkSync(source,path.join(app,'node_modules/@geajs/vite-plugin'))
|
|
26
|
+
assert.equal(resolveAppGeaVitePlugin(app,path.join(core,'package.json')),path.join(source,'index.mjs'))
|
|
27
|
+
fs.unlinkSync(path.join(source,'index.mjs'))
|
|
28
|
+
assert.throws(()=>resolveAppGeaVitePlugin(app,path.join(core,'package.json')),/App declares/)
|
|
29
|
+
} finally { fs.rmSync(root,{recursive:true,force:true}) }
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test('declared app plugin hoisted to its npm workspace root resolves; an unlisted ancestor install does not', () => {
|
|
33
|
+
const root = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'gea-plugin-workspace-')))
|
|
34
|
+
try {
|
|
35
|
+
const app = path.join(root,'apps/clock'), stray = path.join(root,'tools/stray'), core = path.join(root,'core')
|
|
36
|
+
for (const p of [app,stray,core]) fs.mkdirSync(p,{recursive:true})
|
|
37
|
+
for (const p of [app,stray]) fs.writeFileSync(path.join(p,'package.json'),JSON.stringify({devDependencies:{'@geajs/vite-plugin':'^1.4.2'}}))
|
|
38
|
+
fs.writeFileSync(path.join(core,'package.json'),'{}')
|
|
39
|
+
fs.writeFileSync(path.join(root,'package.json'),JSON.stringify({private:true,workspaces:['apps/*']}))
|
|
40
|
+
const pkg=path.join(root,'node_modules/@geajs/vite-plugin'); fs.mkdirSync(pkg,{recursive:true})
|
|
41
|
+
fs.writeFileSync(path.join(pkg,'package.json'),JSON.stringify({name:'@geajs/vite-plugin',version:'1.4.2',type:'module',exports:{'.':{import:'./index.mjs'}}}))
|
|
42
|
+
fs.writeFileSync(path.join(pkg,'index.mjs'),'export const version="1.4.2"')
|
|
43
|
+
assert.equal(resolveAppGeaVitePlugin(app,path.join(core,'package.json')),path.join(pkg,'index.mjs'))
|
|
44
|
+
assert.throws(()=>resolveAppGeaVitePlugin(stray,path.join(core,'package.json')),/App declares/)
|
|
45
|
+
} finally { fs.rmSync(root,{recursive:true,force:true}) }
|
|
46
|
+
})
|