@astrale-os/sdk 0.5.0-beta.76 → 0.5.0-beta.77
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/CHANGELOG.md +7 -0
- package/dist/application/index.d.ts +1 -1
- package/dist/application/view/index.d.ts +1 -1
- package/dist/application/view/route.d.ts +6 -0
- package/dist/application/view/route.js +88 -8
- package/dist/deployment/build/frontend/compilation.d.ts +2 -1
- package/dist/deployment/build/frontend/compilation.js +1 -0
- package/dist/deployment/release/publication/views.js +1 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0-beta.77](https://github.com/astrale-os/sdk/compare/sdk-v0.5.0-beta.76...sdk-v0.5.0-beta.77) (2026-08-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **iframe:** declare view iframe requirements ([#327](https://github.com/astrale-os/sdk/issues/327)) ([ca2e131](https://github.com/astrale-os/sdk/commit/ca2e1311291aee3c62a19cddb33a0b4c13a345d4))
|
|
9
|
+
|
|
3
10
|
## [0.5.0-beta.76](https://github.com/astrale-os/sdk/compare/sdk-v0.5.0-beta.75...sdk-v0.5.0-beta.76) (2026-08-29)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -5,5 +5,5 @@ export type { AdministrationRequirements, AdministrationRequirementsInput, Calla
|
|
|
5
5
|
export { route, routes } from './routes/index.js';
|
|
6
6
|
export type { Route, RouteInput, RouteTarget, Routes } from './routes/index.js';
|
|
7
7
|
export { defineFrontend, external, vite } from './view/index.js';
|
|
8
|
-
export type { Frontend, FrontendInput, FrontendSource } from './view/index.js';
|
|
8
|
+
export type { Frontend, FrontendInput, FrontendSource, IframeRequirements } from './view/index.js';
|
|
9
9
|
export type { Application, ApplicationIdentity, RuntimeOfApplication, SchemaOfApplication, SchemaOfRuntime, } from './application.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { isFrontend } from './admission.js';
|
|
2
2
|
export { defineFrontend } from './define.js';
|
|
3
3
|
export type { Frontend, FrontendInput, FrontendRouteInputs, FrontendRoutes, ViewName, } from './frontend.js';
|
|
4
|
-
export type { FrontendHandshake, FrontendRoute, FrontendRouteInput } from './route.js';
|
|
4
|
+
export type { FrontendHandshake, FrontendRoute, FrontendRouteInput, IframeRequirements, } from './route.js';
|
|
5
5
|
export { external, isFrontendSource, vite } from './source.js';
|
|
6
6
|
export type { ExternalSource, FrontendSource, ViteSource } from './source.js';
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
export type FrontendHandshake = 'shell' | 'none';
|
|
2
|
+
export interface IframeRequirements {
|
|
3
|
+
readonly sandbox?: readonly string[];
|
|
4
|
+
readonly allow?: readonly string[];
|
|
5
|
+
}
|
|
2
6
|
export type FrontendRouteInput = string | {
|
|
3
7
|
readonly path?: string;
|
|
4
8
|
readonly document?: string;
|
|
5
9
|
readonly handshake?: FrontendHandshake;
|
|
10
|
+
readonly iframe?: IframeRequirements;
|
|
6
11
|
};
|
|
7
12
|
export interface FrontendRoute {
|
|
8
13
|
readonly path: string;
|
|
9
14
|
readonly document: string;
|
|
10
15
|
readonly handshake: FrontendHandshake;
|
|
16
|
+
readonly iframe?: IframeRequirements;
|
|
11
17
|
}
|
|
12
18
|
export declare function normalizeRoute(input: FrontendRouteInput | undefined, fallback: string): FrontendRoute;
|
|
13
19
|
export declare function defaultRoute(name: string): string;
|
|
@@ -1,22 +1,102 @@
|
|
|
1
|
+
const TOKEN = /^[a-z][a-z0-9-]*$/u;
|
|
2
|
+
const BASELINES = Object.freeze({
|
|
3
|
+
none: iframeRequirements(['allow-scripts'], []),
|
|
4
|
+
shell: iframeRequirements(['allow-same-origin', 'allow-scripts'], ['clipboard-write']),
|
|
5
|
+
});
|
|
1
6
|
export function normalizeRoute(input, fallback) {
|
|
2
7
|
if (typeof input === 'string') {
|
|
3
8
|
return Object.freeze({ path: routePath(input), document: 'index.html', handshake: 'shell' });
|
|
4
9
|
}
|
|
5
|
-
const value = input ?? {};
|
|
6
|
-
if (value
|
|
7
|
-
invalid();
|
|
8
|
-
if (Reflect.ownKeys(value).some((key) => key !== 'path' && key !== 'document' && key !== 'handshake')) {
|
|
10
|
+
const value = plainRecord(input ?? {});
|
|
11
|
+
if (Reflect.ownKeys(value).some((key) => typeof key !== 'string' || !['path', 'document', 'handshake', 'iframe'].includes(key))) {
|
|
9
12
|
invalid();
|
|
10
13
|
}
|
|
11
|
-
|
|
14
|
+
const authoredHandshake = dataValue(value, 'handshake');
|
|
15
|
+
if (authoredHandshake !== undefined &&
|
|
16
|
+
authoredHandshake !== 'shell' &&
|
|
17
|
+
authoredHandshake !== 'none') {
|
|
12
18
|
invalid();
|
|
13
19
|
}
|
|
20
|
+
const handshake = authoredHandshake ?? 'shell';
|
|
21
|
+
const iframe = normalizeIframeRequirements(dataValue(value, 'iframe'), handshake);
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
path: routePath(dataValue(value, 'path') ?? fallback),
|
|
24
|
+
document: filePath(dataValue(value, 'document') ?? 'index.html'),
|
|
25
|
+
handshake,
|
|
26
|
+
...(iframe === undefined ? {} : { iframe }),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function normalizeIframeRequirements(input, handshake) {
|
|
30
|
+
if (input === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
const value = plainRecord(input);
|
|
33
|
+
if (Reflect.ownKeys(value).some((key) => key !== 'sandbox' && key !== 'allow'))
|
|
34
|
+
invalid();
|
|
35
|
+
const authored = iframeRequirements(tokenArray(dataValue(value, 'sandbox')), tokenArray(dataValue(value, 'allow')));
|
|
36
|
+
assertSandboxRelationships(authored.sandbox);
|
|
37
|
+
const baseline = BASELINES[handshake];
|
|
38
|
+
const sandbox = authored.sandbox.filter((token) => !baseline.sandbox.includes(token));
|
|
39
|
+
const allow = authored.allow.filter((feature) => !baseline.allow.includes(feature));
|
|
40
|
+
return sandbox.length === 0 && allow.length === 0 ? undefined : iframeRequirements(sandbox, allow);
|
|
41
|
+
}
|
|
42
|
+
function iframeRequirements(sandbox, allow) {
|
|
14
43
|
return Object.freeze({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
handshake: value.handshake ?? 'shell',
|
|
44
|
+
sandbox: Object.freeze([...new Set(sandbox)].sort()),
|
|
45
|
+
allow: Object.freeze([...new Set(allow)].sort()),
|
|
18
46
|
});
|
|
19
47
|
}
|
|
48
|
+
function tokenArray(input) {
|
|
49
|
+
if (input === undefined)
|
|
50
|
+
return [];
|
|
51
|
+
if (!Array.isArray(input))
|
|
52
|
+
invalid();
|
|
53
|
+
const descriptors = Object.getOwnPropertyDescriptors(input);
|
|
54
|
+
const result = [];
|
|
55
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
56
|
+
const descriptor = descriptors[String(index)];
|
|
57
|
+
if (descriptor === undefined || !('value' in descriptor))
|
|
58
|
+
invalid();
|
|
59
|
+
if (typeof descriptor.value !== 'string' || !TOKEN.test(descriptor.value))
|
|
60
|
+
invalid();
|
|
61
|
+
result.push(descriptor.value);
|
|
62
|
+
}
|
|
63
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
64
|
+
if (key === 'length')
|
|
65
|
+
continue;
|
|
66
|
+
if (typeof key !== 'string' || !/^(0|[1-9][0-9]*)$/u.test(key) || Number(key) >= input.length) {
|
|
67
|
+
invalid();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
function plainRecord(input) {
|
|
73
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input))
|
|
74
|
+
invalid();
|
|
75
|
+
const prototype = Object.getPrototypeOf(input);
|
|
76
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
77
|
+
invalid();
|
|
78
|
+
return input;
|
|
79
|
+
}
|
|
80
|
+
function dataValue(input, key) {
|
|
81
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, key);
|
|
82
|
+
if (descriptor === undefined)
|
|
83
|
+
return undefined;
|
|
84
|
+
if (!('value' in descriptor))
|
|
85
|
+
invalid();
|
|
86
|
+
return descriptor.value;
|
|
87
|
+
}
|
|
88
|
+
function assertSandboxRelationships(sandbox) {
|
|
89
|
+
const tokens = new Set(sandbox);
|
|
90
|
+
if (tokens.has('allow-popups-to-escape-sandbox') && !tokens.has('allow-popups'))
|
|
91
|
+
invalid();
|
|
92
|
+
if (tokens.has('allow-top-navigation') && tokens.has('allow-top-navigation-by-user-activation')) {
|
|
93
|
+
invalid();
|
|
94
|
+
}
|
|
95
|
+
if (tokens.has('allow-top-navigation-to-custom-protocols') &&
|
|
96
|
+
(tokens.has('allow-top-navigation') || tokens.has('allow-popups'))) {
|
|
97
|
+
invalid();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
20
100
|
export function defaultRoute(name) {
|
|
21
101
|
return routePath(`/${name
|
|
22
102
|
.replace(/([a-z0-9])([A-Z])/gu, '$1-$2')
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Frontend, FrontendSource } from '../../../application/view/index.js';
|
|
2
|
-
import type { FrontendHandshake } from '../../../application/view/index.js';
|
|
2
|
+
import type { FrontendHandshake, IframeRequirements } from '../../../application/view/index.js';
|
|
3
3
|
import type { Key, ViewRef } from '../../../platform/schema/index.js';
|
|
4
4
|
import type { Domain } from '../../../platform/schema/index.js';
|
|
5
5
|
export interface CompiledFrontendRoute {
|
|
@@ -7,6 +7,7 @@ export interface CompiledFrontendRoute {
|
|
|
7
7
|
readonly path: string;
|
|
8
8
|
readonly document: string;
|
|
9
9
|
readonly handshake: FrontendHandshake;
|
|
10
|
+
readonly iframe?: IframeRequirements;
|
|
10
11
|
}
|
|
11
12
|
export interface FrontendCompilation {
|
|
12
13
|
readonly source: FrontendSource;
|
|
@@ -15,6 +15,7 @@ export function compileFrontend(frontend, domain) {
|
|
|
15
15
|
path: route.path,
|
|
16
16
|
document: route.document,
|
|
17
17
|
handshake: route.handshake,
|
|
18
|
+
...(route.iframe === undefined ? {} : { iframe: route.iframe }),
|
|
18
19
|
});
|
|
19
20
|
});
|
|
20
21
|
const entrypoint = domain.views[frontend.entrypoint];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/sdk",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.77",
|
|
4
4
|
"description": "Schema-first SDK for defining, composing, and deploying Astrale domains",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astrale",
|
|
@@ -217,11 +217,11 @@
|
|
|
217
217
|
"registry": "https://registry.npmjs.org/"
|
|
218
218
|
},
|
|
219
219
|
"dependencies": {
|
|
220
|
-
"@astrale-os/kernel-client": "0.6.0-beta.
|
|
221
|
-
"@astrale-os/kernel-core": "0.9.0-beta.
|
|
220
|
+
"@astrale-os/kernel-client": "0.6.0-beta.30",
|
|
221
|
+
"@astrale-os/kernel-core": "0.9.0-beta.23",
|
|
222
222
|
"@astrale-os/kernel-dsl": "0.2.0-beta.17",
|
|
223
|
-
"@astrale-os/kernel-protocol": "0.5.0-beta.
|
|
224
|
-
"@astrale-os/kernel-server": "0.5.0-beta.
|
|
223
|
+
"@astrale-os/kernel-protocol": "0.5.0-beta.24",
|
|
224
|
+
"@astrale-os/kernel-server": "0.5.0-beta.26",
|
|
225
225
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
226
226
|
"hono": "^4.13.2",
|
|
227
227
|
"jose": "^6.2.9",
|