This is an automated email from the ASF dual-hosted git repository.
Harbs pushed a commit to branch codegraph
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/codegraph by this push:
new a28700e730 Add code graph generation and verification to build process
and documentation
a28700e730 is described below
commit a28700e73029afa7ce4286ccc4775b8b409cb009
Author: Harbs <[email protected]>
AuthorDate: Sat Aug 1 22:39:23 2026 +0300
Add code graph generation and verification to build process and
documentation
---
README.md | 43 +++++++++
distribution/pom.xml | 37 ++++++++
distribution/src/main/assembly/codegraphs.xml | 37 ++++++++
frameworks/scripts/verify-codegraph-package.js | 117 +++++++++++++++++++++++++
npm/README.md | 4 +
5 files changed, 238 insertions(+)
diff --git a/README.md b/README.md
index e0123e8745..82e85e2af5 100644
--- a/README.md
+++ b/README.md
@@ -259,6 +259,49 @@ Listing of `option-with-` profiles:
- `option-with-sass-compile`: The Themes contain a lot of Modules, where each
contains SASS resources. Compiling all of these on every build would only slow
down the build. Especially because the SASS resources are only changed very
infrequently. Therefore, the compiled CSS files are checked in. When enabling
this profile the checked in CSS resources are replaced by freshly compiled
versions, which then can be checked in.
- `option-with-swf`: Per default the Royale build only builds the
JavaScript-only version. This can be used to build web-based applications. If
you however wish to build Flash and Air versions, you need to activate this
profile in order for also building the Flash enabled versions of all libraries.
+# Code Graphs
+
+Royale can generate deterministic JSON code graphs of the public framework API
for both JavaScript and SWF targets. The graphs contain public types and
members, ASDoc, metadata, inheritance and reference relationships,
target-specific APIs, Maven dependencies, and MXML tag mappings.
+
+Generate and validate every framework module with Ant:
+
+```bash
+ant -f frameworks/build.xml codegraphs
+node frameworks/scripts/validate-codegraphs.js
+```
+
+Generate one module, or only rebuild the aggregate indexes:
+
+```bash
+ant -Dcodegraph.module=Basic -f frameworks/build.xml codegraph
+ant -f frameworks/build.xml codegraph-index
+```
+
+The Maven build provides the same graphs through the opt-in `codegraphs`
profile. Include `option-with-swf` when building the framework modules so that
both target artifacts are available:
+
+```bash
+./mvnw -f frameworks/projects/pom.xml -Pcodegraphs,option-with-swf -DskipTests
prepare-package
+./mvnw -f distribution/pom.xml -Pcodegraphs -DskipTests verify
+```
+
+The distribution build attaches the graphs as:
+
+```text
+org.apache.royale.framework:distribution:zip:codegraphs:<version>
+```
+
+Binary SDK and npm distributions place the aggregate tree in
`frameworks/codegraphs`. The Maven classifier has the same tree at the archive
root. `index.json` lists module coordinates, target dependencies, shard paths,
counts, and SHA-256 hashes. `mxml.json` maps MXML namespaces and tags to graph
symbols. Graph shards use this layout:
+
+```text
+<version>/<module>/<js|swf>/<module>.json
+```
+
+To verify an extracted aggregate tree independently, run:
+
+```bash
+node frameworks/scripts/verify-codegraph-package.js --root <path-to-codegraphs>
+```
+
# Using Royale
In order to get started using Royale, you are invited to follow along with the
[Quick Start Guide](https://github.com/apache/royale-asjs/wiki/Quick-Start).
diff --git a/distribution/pom.xml b/distribution/pom.xml
index 56bb93037b..6814ebf1a5 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -704,6 +704,43 @@
</target>
</configuration>
</execution>
+ <execution>
+ <id>verify-codegraph-artifact</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <delete
dir="${project.build.directory}/codegraphs-verification"/>
+ <unzip
src="${project.build.directory}/${distributionFileName}-codegraphs.zip"
+
dest="${project.build.directory}/codegraphs-verification"/>
+ <exec executable="node" failonerror="true">
+ <arg
value="${project.basedir}/../frameworks/scripts/verify-codegraph-package.js"/>
+ <arg value="--root"/>
+ <arg
value="${project.build.directory}/codegraphs-verification"/>
+ </exec>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-codegraphs</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/codegraphs.xml</descriptor>
+ </descriptors>
+ </configuration>
+ </execution>
</executions>
</plugin>
</plugins>
diff --git a/distribution/src/main/assembly/codegraphs.xml
b/distribution/src/main/assembly/codegraphs.xml
new file mode 100644
index 0000000000..618e06ffc7
--- /dev/null
+++ b/distribution/src/main/assembly/codegraphs.xml
@@ -0,0 +1,37 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0
http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+ <id>codegraphs</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <fileSets>
+ <fileSet>
+ <directory>${codegraphs.directory}</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>**</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+</assembly>
\ No newline at end of file
diff --git a/frameworks/scripts/verify-codegraph-package.js
b/frameworks/scripts/verify-codegraph-package.js
new file mode 100644
index 0000000000..20c1ecad46
--- /dev/null
+++ b/frameworks/scripts/verify-codegraph-package.js
@@ -0,0 +1,117 @@
+#!/usr/bin/env node
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const crypto = require("crypto");
+const fs = require("fs");
+const path = require("path");
+
+function parseArguments(args) {
+ let root = process.cwd();
+ for (let index = 0; index < args.length; index++) {
+ if (args[index] !== "--root" || index + 1 >= args.length) {
+ throw new Error(`Unknown or incomplete argument: ${args[index]}`);
+ }
+ root = args[++index];
+ }
+ return path.resolve(root);
+}
+
+function readJson(file) {
+ return JSON.parse(fs.readFileSync(file, "utf8"));
+}
+
+function listFiles(root, directory = root) {
+ return fs.readdirSync(directory, { withFileTypes: true }).flatMap(entry =>
{
+ const absolutePath = path.join(directory, entry.name);
+ return entry.isDirectory() ? listFiles(root, absolutePath) :
+ [path.relative(root, absolutePath).split(path.sep).join("/")];
+ });
+}
+
+function resolvePackagedPath(root, relativePath) {
+ const normalizedPath = path.posix.normalize(relativePath);
+ if (normalizedPath !== relativePath || normalizedPath.startsWith("../") ||
path.isAbsolute(relativePath)) {
+ throw new Error(`Invalid packaged path: ${relativePath}`);
+ }
+ return path.join(root, ...relativePath.split("/"));
+}
+
+function main() {
+ const root = parseArguments(process.argv.slice(2));
+ const index = readJson(path.join(root, "index.json"));
+ const mxml = readJson(path.join(root, "mxml.json"));
+ if (index.schemaVersion !== "1.0" || mxml.schemaVersion !==
index.schemaVersion) {
+ throw new Error("Codegraph index schema versions are missing or
inconsistent");
+ }
+ if (!index.version || mxml.version !== index.version ||
!Array.isArray(index.modules)) {
+ throw new Error("Codegraph index versions are missing or
inconsistent");
+ }
+ if (!mxml.targets || !Array.isArray(mxml.targets.js) ||
!Array.isArray(mxml.targets.swf)) {
+ throw new Error("MXML index must contain JS and SWF target mappings");
+ }
+
+ const expectedFiles = new Set(["index.json", "mxml.json"]);
+ const moduleNames = new Set();
+ index.modules.forEach(module => {
+ if (!module.name || moduleNames.has(module.name)) {
+ throw new Error(`Missing or duplicate module name:
${module.name}`);
+ }
+ moduleNames.add(module.name);
+ ["js", "swf"].forEach(target => {
+ const targetIndex = module.targets && module.targets[target];
+ if (!targetIndex || !targetIndex.path || !targetIndex.sha256) {
+ throw new Error(`${module.name} is missing its ${target} graph
index`);
+ }
+ const graphFile = resolvePackagedPath(root, targetIndex.path);
+ const contents = fs.readFileSync(graphFile);
+ const digest =
crypto.createHash("sha256").update(contents).digest("hex");
+ if (digest !== targetIndex.sha256) {
+ throw new Error(`${targetIndex.path} does not match its
SHA-256 index`);
+ }
+ const graph = JSON.parse(contents.toString("utf8"));
+ if (graph.schemaVersion !== index.schemaVersion || graph.module
!== module.name || graph.target !== target) {
+ throw new Error(`${targetIndex.path} has inconsistent graph
identity`);
+ }
+ if (!Array.isArray(graph.symbols) || graph.symbols.length !==
targetIndex.symbolCount) {
+ throw new Error(`${targetIndex.path} has an inconsistent
symbol count`);
+ }
+ const classCount = graph.symbols.filter(symbol => symbol.kind ===
"class").length;
+ if (classCount !== targetIndex.classCount) {
+ throw new Error(`${targetIndex.path} has an inconsistent class
count`);
+ }
+ expectedFiles.add(targetIndex.path);
+ });
+ });
+
+ const actualFiles = listFiles(root);
+ const unexpectedFiles = actualFiles.filter(file =>
!expectedFiles.has(file));
+ const missingFiles = Array.from(expectedFiles).filter(file =>
!actualFiles.includes(file));
+ if (unexpectedFiles.length || missingFiles.length) {
+ throw new Error(`Package membership mismatch; missing:
${missingFiles.join(", ") || "none"}; ` +
+ `unexpected: ${unexpectedFiles.join(", ") || "none"}`);
+ }
+ console.log(`Verified packaged codegraphs for ${index.modules.length}
module(s) and ${actualFiles.length} file(s).`);
+}
+
+try {
+ main();
+} catch (error) {
+ console.error(error.message);
+ process.exitCode = 1;
+}
\ No newline at end of file
diff --git a/npm/README.md b/npm/README.md
index 37416dd5da..682ed3be2c 100644
--- a/npm/README.md
+++ b/npm/README.md
@@ -41,6 +41,10 @@ node publish.js --type=js-only
--pathToTarball=path-to-tgz-file --username=npm-u
node publish.js --type=js-swf --pathToTarball=path-to-tgz-file
--username=npm-username --password=npm-password
```
+Both release tarballs must contain the generated public API code graphs under
+`royale-asjs/frameworks/codegraphs`, including `index.json` and `mxml.json`.
+The npm publisher streams the supplied tarball unchanged.
+
For example:
```
node publish.js --type=js-only
--pathToTarball="C:\p\os\flexroot\royale\royale-asjs\out\binaries\apache-royale-0.9.0-bin-js.tar.gz"
--username=apache-royale-owner --password=shared_in_private