@kubohiroya/turbowarp-structured-data 0.6.2 → 0.7.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.ja.md +38 -0
- package/README.md +61 -7
- package/dist/structured-data.js +43 -22
- package/docs/.nojekyll +0 -0
- package/docs/assets/github-mark.svg +1 -0
- package/docs/assets/site.css +847 -0
- package/docs/index.html +577 -21
- package/docs/ja/index.html +549 -0
- package/lib-editor/src/config.d.ts +6 -0
- package/lib-module/src/bundle-module.d.ts +7 -0
- package/lib-module/src/bundle-module.js +1384 -0
- package/lib-module/src/codecs.d.ts +10 -0
- package/lib-module/src/config.d.ts +25 -0
- package/lib-module/src/core.d.ts +34 -0
- package/lib-module/src/editor-schema.d.ts +2 -0
- package/lib-module/src/extension.d.ts +74 -0
- package/lib-module/src/fixed-input-editors.d.ts +9 -0
- package/lib-module/src/fixed-input-schema.d.ts +3 -0
- package/lib-module/src/runtime-api.d.ts +41 -0
- package/lib-module/src/source-editor.d.ts +8 -0
- package/lib-module/src/structured-provider.d.ts +33 -0
- package/package.json +19 -11
- package/src/bundle-module.ts +23 -0
- package/src/config.ts +11 -0
- package/src/extension.ts +17 -15
- package/src/globals.d.ts +7 -36
- package/src/index.ts +2 -2
- package/src/runtime-api.ts +43 -0
- package/src/structured-provider.ts +38 -7
- package/templates/README.ja.md +36 -0
- package/templates/README.md +48 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {renderJsonDocument, renderYamlDocument} from './codecs.js';
|
|
2
|
+
import {isNamedDataSchemaRefEnabled} from './config.js';
|
|
2
3
|
import type {JsonValue} from './core.js';
|
|
3
4
|
import {
|
|
4
5
|
NamedDataError,
|
|
@@ -6,6 +7,7 @@ import {
|
|
|
6
7
|
type NamedDataMetadata,
|
|
7
8
|
type NamedDataProvider,
|
|
8
9
|
type NamedDataReference,
|
|
10
|
+
type NamedDataSchemaRef,
|
|
9
11
|
type NamedDataRepresentation,
|
|
10
12
|
type NamedDataResolveContext
|
|
11
13
|
} from '@kubohiroya/turbowarp-named-data/composition';
|
|
@@ -17,6 +19,7 @@ export interface StructuredDataBinding {
|
|
|
17
19
|
value: JsonValue;
|
|
18
20
|
revision: number;
|
|
19
21
|
nativeRepresentation: 'json' | 'yaml';
|
|
22
|
+
schemaRef?: NamedDataSchemaRef;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
export interface StructuredDataBindingStore {
|
|
@@ -31,7 +34,8 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
31
34
|
|
|
32
35
|
public constructor(
|
|
33
36
|
private readonly store: StructuredDataBindingStore,
|
|
34
|
-
private readonly maxBodyBytes = STRUCTURED_BODY_MAX_BYTES
|
|
37
|
+
private readonly maxBodyBytes = STRUCTURED_BODY_MAX_BYTES,
|
|
38
|
+
private readonly schemaRefEnabled = isNamedDataSchemaRefEnabled()
|
|
35
39
|
) {}
|
|
36
40
|
|
|
37
41
|
public canResolve(
|
|
@@ -57,7 +61,8 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
57
61
|
resolved.nativeRepresentation,
|
|
58
62
|
representation,
|
|
59
63
|
resolved.bytes.byteLength,
|
|
60
|
-
resolved.revision
|
|
64
|
+
resolved.revision,
|
|
65
|
+
resolved.schemaRef
|
|
61
66
|
);
|
|
62
67
|
}
|
|
63
68
|
|
|
@@ -76,7 +81,8 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
76
81
|
resolved.nativeRepresentation,
|
|
77
82
|
representation,
|
|
78
83
|
resolved.bytes.byteLength,
|
|
79
|
-
resolved.revision
|
|
84
|
+
resolved.revision,
|
|
85
|
+
resolved.schemaRef
|
|
80
86
|
),
|
|
81
87
|
body: resolved.bytes,
|
|
82
88
|
release: () => {
|
|
@@ -100,7 +106,12 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
100
106
|
reference: NamedDataReference,
|
|
101
107
|
representation: NamedDataRepresentation,
|
|
102
108
|
context: NamedDataResolveContext
|
|
103
|
-
): {
|
|
109
|
+
): {
|
|
110
|
+
bytes: Uint8Array;
|
|
111
|
+
revision: number;
|
|
112
|
+
nativeRepresentation: 'json' | 'yaml';
|
|
113
|
+
schemaRef?: NamedDataSchemaRef;
|
|
114
|
+
} {
|
|
104
115
|
if (this.released) {
|
|
105
116
|
throw new NamedDataError('NAMED_DATA_PROVIDER_RELEASED', 'The structured provider was released.');
|
|
106
117
|
}
|
|
@@ -113,6 +124,23 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
113
124
|
`Structured data does not exist: ${reference.name}`
|
|
114
125
|
);
|
|
115
126
|
}
|
|
127
|
+
const requestedSchemaRef = reference.schemaRef;
|
|
128
|
+
if (requestedSchemaRef !== undefined && !this.schemaRefEnabled) {
|
|
129
|
+
throw new NamedDataError(
|
|
130
|
+
'NAMED_DATA_SCHEMA_UNRESOLVED',
|
|
131
|
+
'Schema reference resolution is disabled.'
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
if (
|
|
135
|
+
requestedSchemaRef !== undefined &&
|
|
136
|
+
(binding.schemaRef?.id !== requestedSchemaRef.id ||
|
|
137
|
+
binding.schemaRef?.version !== requestedSchemaRef.version)
|
|
138
|
+
) {
|
|
139
|
+
throw new NamedDataError(
|
|
140
|
+
'NAMED_DATA_SCHEMA_VERSION_MISMATCH',
|
|
141
|
+
'Binding schemaRef does not match the requested reference.'
|
|
142
|
+
);
|
|
143
|
+
}
|
|
116
144
|
const text = this.render(binding.value, representation);
|
|
117
145
|
const bytes = new TextEncoder().encode(text);
|
|
118
146
|
if (bytes.byteLength > this.maxBodyBytes) {
|
|
@@ -125,7 +153,8 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
125
153
|
return {
|
|
126
154
|
bytes,
|
|
127
155
|
revision: binding.revision,
|
|
128
|
-
nativeRepresentation: binding.nativeRepresentation
|
|
156
|
+
nativeRepresentation: binding.nativeRepresentation,
|
|
157
|
+
...(requestedSchemaRef === undefined ? {} : {schemaRef: binding.schemaRef})
|
|
129
158
|
};
|
|
130
159
|
}
|
|
131
160
|
|
|
@@ -164,7 +193,8 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
164
193
|
nativeRepresentation: 'json' | 'yaml',
|
|
165
194
|
representation: NamedDataRepresentation,
|
|
166
195
|
byteLength: number,
|
|
167
|
-
revision: number
|
|
196
|
+
revision: number,
|
|
197
|
+
schemaRef?: NamedDataSchemaRef
|
|
168
198
|
): NamedDataMetadata {
|
|
169
199
|
return {
|
|
170
200
|
reference: {...reference},
|
|
@@ -176,7 +206,8 @@ export class StructuredDataNamedDataProvider implements NamedDataProvider {
|
|
|
176
206
|
: 'application/yaml; charset=utf-8',
|
|
177
207
|
byteLength,
|
|
178
208
|
revision: String(revision),
|
|
179
|
-
replayable: true
|
|
209
|
+
replayable: true,
|
|
210
|
+
...(schemaRef === undefined ? {} : {schemaRef})
|
|
180
211
|
};
|
|
181
212
|
}
|
|
182
213
|
|
package/templates/README.ja.md
CHANGED
|
@@ -144,6 +144,42 @@ renderer境界、`release()`/`releaseAll()`を説明します。
|
|
|
144
144
|
|
|
145
145
|
extension IDまたはopcode変更時はschema-aware migrationを説明し、保存済み識別子が変わった場合にJavaScriptだけの差替えを案内しません。
|
|
146
146
|
|
|
147
|
+
## 統合ビルド用module API
|
|
148
|
+
|
|
149
|
+
このソースのbuildは、単体JSとは別に、統合用のESM入口`./bundle-module`と
|
|
150
|
+
型宣言を`lib-module/`へ生成します。
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import {bundleModuleMetadata, createExtension, type ScratchApi}
|
|
154
|
+
from '@kubohiroya/<package>/bundle-module';
|
|
155
|
+
|
|
156
|
+
export function createMember(memberScratch: ScratchApi) {
|
|
157
|
+
return createExtension(memberScratch);
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
import時はglobal Scratch / window / documentを参照せず、拡張の生成・登録を行いません。
|
|
162
|
+
明示的なcreateExtension(memberScratch)ごとに新しいinstanceを返し、後から実行する
|
|
163
|
+
ブロック・編集用補助処理・lifecycle callbackも同じhostを使います。factoryは
|
|
164
|
+
Scratch.extensions.registerを呼びません。単体entryも同じfactoryを使い、登録は1回です。
|
|
165
|
+
|
|
166
|
+
凍結されたbundleModuleMetadataはformatVersion: 1、元のid、unsandboxed条件を
|
|
167
|
+
宣言します。統合hostが生成前に検査し、登録とdisposeを管理します。ID・opcode・
|
|
168
|
+
保存データ形式を変更しません。
|
|
169
|
+
|
|
170
|
+
既存のSTRUCTURED_DATA_MVP・NAMED_DATA_REGISTRY_MVP・Schema参照の起動フラグと既定値を維持します。生成時の任意の編集登録・named-data初期化には注入hostを使います。dispose()をawaitして、このinstanceの登録とlistenerを解除します。StructuredDataExtensionを直接newする内部コードでは、hostを先頭に渡し、その後に従来の任意の機能フラグ引数を渡します。
|
|
171
|
+
|
|
172
|
+
yaml等のruntime依存とそのsubpathは外部importのまま保持します。既存の小さな編集用
|
|
173
|
+
純粋ヘルパーだけを含め、production consumerには編集packageやGUIエンジンを要求しません。
|
|
174
|
+
公開型は既存tsconfigと同じES2022の型ライブラリを使い、生成JSはES2020を対象とします。
|
|
175
|
+
既存exportsを維持して./bundle-moduleを追加し、templateへのruntime依存は追加しません。
|
|
176
|
+
|
|
177
|
+
pnpm run build:moduleで生成し、pnpm run check:moduleは実tarballをproduction依存だけの
|
|
178
|
+
consumerへinstallしてhost分離・単体版との動作一致・公開型・編集エンジンの非混入を検査します。
|
|
179
|
+
sb3-toolchain側の統合buildは[sb3-toolchain #65](https://github.com/kubohiroya/sb3-toolchain/issues/65)の後続です。
|
|
180
|
+
切戻しはこのmodule入口を選択せず従来のclassic distを読み込みます。新しいruntimeフラグや
|
|
181
|
+
保存データの移行は導入しません。
|
|
182
|
+
|
|
147
183
|
## 開発
|
|
148
184
|
|
|
149
185
|
`engines`のNode.jsと、`packageManager`に宣言したpnpmを使用します。
|
package/templates/README.md
CHANGED
|
@@ -154,6 +154,48 @@ for example `TurboWarp-Asset-Manager`, `TurboWarp-Runtime-Expression`, and
|
|
|
154
154
|
Document schema-aware migrations when an extension ID or opcode changes. Never
|
|
155
155
|
instruct users to replace JavaScript alone when stored identifiers have changed.
|
|
156
156
|
|
|
157
|
+
## Integrated-build module API
|
|
158
|
+
|
|
159
|
+
Building this source also produces a `./bundle-module` ESM entry and declarations
|
|
160
|
+
in `lib-module/`. This entry is separate from the standalone JavaScript file.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import {bundleModuleMetadata, createExtension, type ScratchApi}
|
|
164
|
+
from '@kubohiroya/<package>/bundle-module';
|
|
165
|
+
|
|
166
|
+
export function createMember(memberScratch: ScratchApi) {
|
|
167
|
+
return createExtension(memberScratch);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Importing the entry does not access global Scratch / window / document or create
|
|
172
|
+
and register an extension. Each explicit createExtension(memberScratch) call
|
|
173
|
+
returns a fresh instance bound to that host, including deferred block execution,
|
|
174
|
+
editor helpers and lifecycle callbacks. The factory does not call
|
|
175
|
+
Scratch.extensions.register; the standalone entry uses the same factory and
|
|
176
|
+
registers exactly once.
|
|
177
|
+
|
|
178
|
+
The frozen bundleModuleMetadata declares formatVersion: 1, the original id and
|
|
179
|
+
unsandboxed requirement. An integrated host validates these before creation and
|
|
180
|
+
owns registration and disposal. Existing IDs, opcodes and saved data stay unchanged.
|
|
181
|
+
|
|
182
|
+
The existing STRUCTURED_DATA_MVP, NAMED_DATA_REGISTRY_MVP and Schema reference startup flags retain their defaults. Creation performs the existing optional editor and named-data initialization against the injected host. Call and await dispose() to release the instance registrations and listeners. Internal callers constructing StructuredDataExtension directly now pass the host first, followed by the existing optional feature arguments.
|
|
183
|
+
|
|
184
|
+
Runtime dependencies (including yaml and their subpaths) remain external imports.
|
|
185
|
+
Only the existing small, pure development-time editor helpers are included, so
|
|
186
|
+
production consumers need no editor package or GUI engine. Public types use the
|
|
187
|
+
same ES2022 libraries as the project tsconfig; generated JavaScript targets ES2020.
|
|
188
|
+
The package retains its existing exports and adds ./bundle-module; no template
|
|
189
|
+
runtime dependency is required.
|
|
190
|
+
|
|
191
|
+
pnpm run build:module builds this entry; pnpm run check:module packs and installs
|
|
192
|
+
the actual package with production dependencies only, checks host isolation,
|
|
193
|
+
standalone parity and public types, and rejects editor-engine dependency leaks.
|
|
194
|
+
The integrated sb3-toolchain build remains a later step in
|
|
195
|
+
[sb3-toolchain #65](https://github.com/kubohiroya/sb3-toolchain/issues/65).
|
|
196
|
+
To roll back, continue loading the existing classic dist artifact without selecting
|
|
197
|
+
this module entry. No runtime flag or saved-data migration is introduced.
|
|
198
|
+
|
|
157
199
|
## Development
|
|
158
200
|
|
|
159
201
|
Use Node.js `<minimum version>` and the pnpm version declared by
|
|
@@ -197,15 +239,15 @@ site and `blockIconURI` remains a `data:image/svg+xml;base64,...` URI.
|
|
|
197
239
|
Third-party components, when present, are listed in
|
|
198
240
|
[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).
|
|
199
241
|
|
|
200
|
-
##
|
|
242
|
+
## Fixed-input editor form (S3-4)
|
|
201
243
|
|
|
202
|
-
|
|
244
|
+
When the shared editor's startup flag `blockEditorFixedInputs` and Dialogs are both on in the GUI, the extension registers a fixed form for `forEachAtPath`'s `MAX` input only. Older GUIs, or a GUI with the flag off, get no extra registration. The canonical Schema is `schemas/block-editor-fixed-inputs.schema.json#/$defs/forEachAtPath/properties/MAX`; the codec and registration live in `src/fixed-input-editors.ts`. Saving without changes never rewrites existing raw values, unchanged aliases, or unknown enum values, and connected reporters are never evaluated. Only explicit changes are validated; other arguments, block declarations, and the saved format are unchanged.
|
|
203
245
|
|
|
204
|
-
MAX
|
|
246
|
+
`MAX` is an integer from 1 to 1000. New input also follows the shared finite-number token rule, and partial input is not saved. When the MVP flag is off nothing is registered, and whether `NAME`/`PATH` accept connected reporters (derived from `staticLiteral`) does not change.
|
|
205
247
|
|
|
206
|
-
|
|
248
|
+
Registration is limited to the optional API (`apiVersion: 1`) and is released on `RUNTIME_DISPOSED` or an explicit dispose. Turning the startup flag off and reloading restores the previous behavior. When rolling back the dependency, restore the manifest, lockfile, and actual resolution together. This stage does not include an npm release or dynamic candidates from later stages.
|
|
207
249
|
|
|
208
|
-
Schema
|
|
209
|
-
|
|
250
|
+
The contract the Schema describes is grounded in the actual `getInfo` declarations and the existing pure runtime conversions. The SchemaBundle `retrievalUri` identifies this local document; it does not mean the Schema is served from that URL or that `$ref` is resolved over HTTP. The Schema compiles from the bundled documents only.
|
|
251
|
+
Existing non-empty finite Number aliases for `MAX` (for example `001`, `+1`, or `0x10`) are only projected through `Number` for display; unchanged raw values are not saved again. Blank, non-finite, or unprojectable values are read-only, and no `0` or default is substituted. New input does not accept these aliases and follows NP-finite-new-input-v1.
|
|
210
252
|
|
|
211
253
|
Registration uses the optional editor API available when the extension instance is constructed. Adding or replacing that API later is not followed automatically; reload the GUI and reconstruct the extension instance after changing the startup configuration.
|