157 lines
5.0 KiB
TypeScript
157 lines
5.0 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import {
|
|
applicationCoverageSchema,
|
|
applicationGraphEvidenceSchema,
|
|
applicationNodeIdentitySchema,
|
|
} from "./javascriptApplicationEvidenceSchemas.js";
|
|
import { isJsonWithinDepth } from "./jsonLimits.js";
|
|
import { jsonValueSchema } from "./jsonValue.js";
|
|
|
|
const boundedTextSchema = z.string().min(1);
|
|
|
|
/** Node kinds admitted by JavaScript Application Graph. */
|
|
export const JAVASCRIPT_APPLICATION_NODE_KINDS = [
|
|
"package",
|
|
"installer",
|
|
"artifact",
|
|
"asar-entry",
|
|
"electron-main",
|
|
"electron-preload",
|
|
"electron-renderer",
|
|
"electron-utility",
|
|
"javascript-asset",
|
|
"javascript-chunk",
|
|
"javascript-module",
|
|
"source-map",
|
|
"source-module",
|
|
"browser-window",
|
|
"frame",
|
|
"target",
|
|
"context-bridge-api",
|
|
"ipc-channel",
|
|
"ipc-handler",
|
|
"worker",
|
|
"service-worker",
|
|
"endpoint",
|
|
"storage",
|
|
"native-addon",
|
|
"native-export",
|
|
"managed-assembly",
|
|
"managed-module",
|
|
"managed-type",
|
|
"managed-method",
|
|
"managed-field",
|
|
"managed-pinvoke-import",
|
|
"managed-native-implementation",
|
|
"runtime-script-instance",
|
|
"unknown",
|
|
] as const;
|
|
|
|
/** Provider-neutral application entity categories. */
|
|
const applicationNodeKindSchema = z.enum(JAVASCRIPT_APPLICATION_NODE_KINDS);
|
|
|
|
/** Directed relations admitted by JavaScript Application Graph. */
|
|
export const JAVASCRIPT_APPLICATION_RELATIONS = [
|
|
"contains",
|
|
"loads",
|
|
"imports",
|
|
"maps_to",
|
|
"exposes",
|
|
"sends",
|
|
"invokes",
|
|
"handles",
|
|
"calls",
|
|
"persists_to",
|
|
"observed_as",
|
|
"changed_from",
|
|
] as const;
|
|
|
|
/** Provider-neutral relation categories. */
|
|
const applicationRelationSchema = z.enum(JAVASCRIPT_APPLICATION_RELATIONS);
|
|
|
|
const applicationPropertiesSchema = z
|
|
.record(z.string().min(1), jsonValueSchema)
|
|
.superRefine((properties, context) => {
|
|
if (!isJsonWithinDepth(properties, 6))
|
|
context.addIssue({
|
|
code: "custom",
|
|
message: "Application graph properties exceed the supported depth",
|
|
});
|
|
});
|
|
|
|
/** One node observation before its semantic identifier is derived. */
|
|
const applicationNodeObservationInputSchema = z.strictObject({
|
|
label: z.string().min(1).nullable(),
|
|
properties: applicationPropertiesSchema,
|
|
evidence: applicationGraphEvidenceSchema,
|
|
});
|
|
|
|
/** One immutable, evidence-bearing observation attached to an entity. */
|
|
export const applicationNodeObservationSchema =
|
|
applicationNodeObservationInputSchema.extend({
|
|
observation_id: z.string().regex(/^jag_observation_[a-f0-9]{64}$/u),
|
|
identifier_strategy: z.strictObject({
|
|
strategy: z.literal("semantic-content-sha256"),
|
|
stability: z.literal("observation-exact"),
|
|
}),
|
|
});
|
|
|
|
/** One application entity before its stable identifier is derived. */
|
|
export const applicationNodeInputSchema = z.strictObject({
|
|
kind: applicationNodeKindSchema,
|
|
identity: applicationNodeIdentitySchema,
|
|
observations: z.array(applicationNodeObservationInputSchema).min(1),
|
|
});
|
|
|
|
/** One stable application entity with one or more bounded observations. */
|
|
export const applicationNodeSchema = z.strictObject({
|
|
node_id: z.string().regex(/^jag_node_[a-f0-9]{64}$/u),
|
|
kind: applicationNodeKindSchema,
|
|
identity: applicationNodeIdentitySchema,
|
|
observations: z.array(applicationNodeObservationSchema).min(1),
|
|
});
|
|
|
|
/** One directed relationship before its semantic identifier is derived. */
|
|
export const applicationEdgeInputSchema = z.strictObject({
|
|
source_node_id: z.string().regex(/^jag_node_[a-f0-9]{64}$/u),
|
|
target_node_id: z.string().regex(/^jag_node_[a-f0-9]{64}$/u),
|
|
relation: applicationRelationSchema,
|
|
properties: applicationPropertiesSchema,
|
|
evidence: applicationGraphEvidenceSchema,
|
|
});
|
|
|
|
/** One directed, evidence-bearing application relationship. */
|
|
export const applicationEdgeSchema = applicationEdgeInputSchema.extend({
|
|
edge_id: z.string().regex(/^jag_edge_[a-f0-9]{64}$/u),
|
|
identifier_strategy: z.strictObject({
|
|
strategy: z.literal("semantic-content-sha256"),
|
|
stability: z.literal("relationship-exact"),
|
|
}),
|
|
});
|
|
|
|
/** Graph content before its top-level semantic identifier is derived. */
|
|
export const javascriptApplicationGraphInputSchema = z.strictObject({
|
|
schema: z.literal("JavaScriptApplicationGraph"),
|
|
root_node_ids: z.array(z.string().regex(/^jag_node_[a-f0-9]{64}$/u)).min(1),
|
|
nodes: z.array(applicationNodeSchema).min(1),
|
|
edges: z.array(applicationEdgeSchema),
|
|
coverage: applicationCoverageSchema,
|
|
limitations: z.array(boundedTextSchema),
|
|
});
|
|
|
|
/** Strict stored shape for a JavaScript Application Graph. */
|
|
export const javascriptApplicationGraphRecordSchema =
|
|
javascriptApplicationGraphInputSchema.extend({
|
|
graph_id: z.string().regex(/^jag_[a-f0-9]{64}$/u),
|
|
});
|
|
|
|
/** Immutable entity in a JavaScript Application Graph. */
|
|
export type ApplicationNode = z.infer<typeof applicationNodeSchema>;
|
|
/** Immutable relationship in a JavaScript Application Graph. */
|
|
export type ApplicationEdge = z.infer<typeof applicationEdgeSchema>;
|
|
/** Complete graph content before its graph identifier is derived. */
|
|
export type JavaScriptApplicationGraphInput = z.infer<
|
|
typeof javascriptApplicationGraphInputSchema
|
|
>;
|