pi-apexlang 0.2.1 → 0.2.2

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 CHANGED
@@ -103,6 +103,45 @@ repeat export produces one current snapshot instead of collision copies such
103
103
  as `application_1.apx` and `p00005_1.apx`. Because this replaces the complete
104
104
  local export, preserve or import any local-only work before refreshing it.
105
105
 
106
+ ## SQLcl and ORDS compatibility advisory
107
+
108
+ Oracle documents minimum APEXlang prerequisites, but does not publish an exact
109
+ ORDS-to-SQLcl patch certification matrix. The extension therefore keeps this
110
+ mapping advisory and records whether a row is Oracle-confirmed or an extension
111
+ diagnostic recommendation:
112
+
113
+ | Server environment | SQLcl guidance | Basis |
114
+ | --- | --- | --- |
115
+ | ORDS before 26.1.1 or APEX before 26.1 | APEXlang is unsupported; upgrade the server components first. | Oracle-confirmed |
116
+ | APEX 26.1.x with ORDS 26.1.1 through 26.1.x | Oracle minimum: SQLcl 26.1. Diagnostic baseline: `26.1.2.132.1334`. | Oracle minimum plus extension advisory |
117
+ | APEX 26.1.x with ORDS 26.2.x | Oracle does not mandate SQLcl 26.2. On mass findings, compare with `26.1.2.132.1334`. | Extension advisory |
118
+ | Other or newer APEX, MMD, or ORDS lines | Verify current Oracle release documentation and use compiler metadata supporting the app `mmdVersion`. | Verify current docs |
119
+
120
+ The complete machine-readable table, source URLs, thresholds, and the direct
121
+ diagnostic-build download are in
122
+ [`extensions/apexlang/ords-sqlcl-compatibility.json`](extensions/apexlang/ords-sqlcl-compatibility.json).
123
+ The exact build is a known diagnostic baseline, not a universal pin, and SQLcl
124
+ 26.2 is not categorically blocked.
125
+
126
+ When a validation result contains at least 50 structured findings, the
127
+ extension appends the table and recommends checking:
128
+
129
+ - local `sql -version`;
130
+ - the app's `.apex/apexlang.json` `mmdVersion`;
131
+ - the server APEX release and ORDS version with its administrator.
132
+
133
+ For local and compiler-truth text reports, the mass-error signal additionally
134
+ requires at least five distinct `.apx` files, which avoids treating one noisy
135
+ file as an environment-wide mismatch. An explicitly unsupported MMD version
136
+ also produces the compatibility advice. The advice never changes validation
137
+ status, relaxes an import gate, or claims that the application is valid.
138
+
139
+ [ORDS 26.1.1 introduced APEXlang support](https://www.oracle.com/tools/ords/ords-relnotes-26.1.1.html),
140
+ [APEX 26.1 requires ORDS 26.1.1 or later](https://docs.oracle.com/en/database/oracle/apex/26.1/htmrn/changed-behavior.html),
141
+ and Oracle's [SQLcl prerequisites](https://docs.oracle.com/en/database/oracle/sql-developer-command-line/26.1/sqcug/prerequisites-apexlang.html)
142
+ set the SQLcl minimum at 26.1. SQLcl
143
+ [26.1.2 added full APEXlang support](https://www.oracle.com/tools/sqlcl/sqlcl-relnotes-26.1.2.html).
144
+
106
145
  All app paths must remain inside the active Pi workspace. The adapter rejects
107
146
  traversal, app-tree symlinks, and multiply linked files on mutating vocabulary
108
147
  fixes; verifies live workspace input against `deployments/default.json`; and
@@ -116,8 +155,9 @@ Offline routing, templates, generation, and most local checks need Node.js
116
155
 
117
156
  Oracle documents these requirements for live APEXlang work:
118
157
 
119
- - Oracle APEX with APEXlang support, using the latest available 26.1 build.
120
- - SQLcl 26.1.2 or newer.
158
+ - Oracle APEX 26.1 with APEXlang support.
159
+ - ORDS 26.1.1 or newer.
160
+ - SQLcl 26.1 or newer, selected with the compatibility advisory above.
121
161
  - Java 17 or Java 21 for SQLcl.
122
162
  - A saved SQLcl connection name and its corresponding APEX workspace name.
123
163
  - A local APEX app or authoritative schema, model, API, or table metadata.
@@ -0,0 +1,227 @@
1
+ import { readFile, rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import compatibility from "./ords-sqlcl-compatibility.json" with { type: "json" };
4
+ import type { ApexlangRunResult } from "../lib/apexlang-cli.mjs";
5
+
6
+ type JsonRecord = Record<string, unknown>;
7
+
8
+ export type ValidationCompatibilitySignal = {
9
+ findingCount?: number;
10
+ distinctFileCount?: number;
11
+ source: "structured-result" | "local-reports" | "compiler-truth-output" | "unsupported-mmd";
12
+ };
13
+
14
+ export const ORDS_SQLCL_COMPATIBILITY = compatibility;
15
+ export const ORDS_SQLCL_COMPATIBILITY_TABLE = compatibility.rows;
16
+ export const MASS_VALIDATION_FINDING_THRESHOLD = compatibility.massValidation.minimumFindings;
17
+ export const MASS_VALIDATION_DISTINCT_FILE_THRESHOLD =
18
+ compatibility.massValidation.minimumDistinctFilesForAppWideReports;
19
+ export const ORDS_SQLCL_COMPATIBILITY_GUIDELINE =
20
+ `When a validation action reports ${MASS_VALIDATION_FINDING_THRESHOLD}+ findings, recommend checking the server APEX/ORDS release, the app mmdVersion, and local \`sql -version\` against the extension's advisory compatibility table. For APEX 26.1, SQLcl 26.1 is Oracle's minimum and 26.1.2.132.1334 is the diagnostic baseline; do not hard-block other SQLcl versions or weaken validation/import gates.`;
21
+
22
+ const VALIDATION_ACTIONS = new Set([
23
+ "local_validate",
24
+ "compiler_truth_audit",
25
+ "runtime_validate"
26
+ ]);
27
+ const LOCAL_VALIDATION_REPORT_NAMES = [
28
+ "apexlang-dsl-report.json",
29
+ "apexlang-validations-report.json",
30
+ "apexlang-vocab-report.json"
31
+ ] as const;
32
+
33
+ function asRecord(value: unknown): JsonRecord | undefined {
34
+ return value !== null && typeof value === "object" && !Array.isArray(value)
35
+ ? value as JsonRecord
36
+ : undefined;
37
+ }
38
+
39
+ function parseJsonRecord(value: string): JsonRecord | undefined {
40
+ try {
41
+ return asRecord(JSON.parse(value));
42
+ } catch {
43
+ return undefined;
44
+ }
45
+ }
46
+
47
+ function safeCount(value: unknown): number | undefined {
48
+ return Number.isSafeInteger(value) && Number(value) >= 0 ? Number(value) : undefined;
49
+ }
50
+
51
+ function maximumStructuredFindingCount(payload: JsonRecord): number | undefined {
52
+ const compatibilityFallback = asRecord(payload.compatibility_fallback);
53
+ const candidates = [
54
+ safeCount(payload.unresolved_count),
55
+ safeCount(payload.problem_count),
56
+ Array.isArray(payload.issues) ? payload.issues.length : undefined,
57
+ Array.isArray(payload.problems) ? payload.problems.length : undefined,
58
+ safeCount(compatibilityFallback?.original_unresolved_count)
59
+ ].filter((value): value is number => value !== undefined);
60
+ return candidates.length > 0 ? Math.max(...candidates) : undefined;
61
+ }
62
+
63
+ function diagnosticIdentity(issue: unknown, reportName: string, index: number): {
64
+ key: string;
65
+ file?: string;
66
+ } {
67
+ if (typeof issue === "string") {
68
+ const raw = issue.trim();
69
+ const match = raw.match(/^\s*-?\s*(.+?\.apx):(\d+)(?::\d+)?:\s+[A-Z][A-Z0-9_]+\b/);
70
+ return { key: raw || `${reportName}:${index}`, ...(match?.[1] ? { file: match[1] } : {}) };
71
+ }
72
+
73
+ const record = asRecord(issue);
74
+ if (!record) return { key: `${reportName}:${index}:${String(issue)}` };
75
+ const file = typeof record.file === "string" ? record.file.trim() : "";
76
+ const raw = typeof record.raw === "string" ? record.raw.trim() : "";
77
+ const key = raw || [
78
+ file,
79
+ String(record.line ?? ""),
80
+ String(record.column ?? ""),
81
+ String(record.rule ?? record.code ?? ""),
82
+ String(record.message ?? "")
83
+ ].join(":");
84
+ return {
85
+ key: key || `${reportName}:${index}:${JSON.stringify(record)}`,
86
+ ...(file ? { file } : {})
87
+ };
88
+ }
89
+
90
+ async function readJsonReport(path: string): Promise<JsonRecord | undefined> {
91
+ try {
92
+ return parseJsonRecord(await readFile(path, "utf8"));
93
+ } catch {
94
+ return undefined;
95
+ }
96
+ }
97
+
98
+ export async function clearLocalValidationCompatibilityReports(outputRoot: string): Promise<void> {
99
+ await Promise.all(
100
+ LOCAL_VALIDATION_REPORT_NAMES.map((name) => rm(join(outputRoot, "logs", name), { force: true }))
101
+ );
102
+ }
103
+
104
+ async function detectLocalReportSignal(outputRoot: string): Promise<ValidationCompatibilitySignal | undefined> {
105
+ const reports = await Promise.all(
106
+ LOCAL_VALIDATION_REPORT_NAMES.map(async (name) => ({
107
+ name,
108
+ payload: await readJsonReport(join(outputRoot, "logs", name))
109
+ }))
110
+ );
111
+ const vocabularyReport = reports.find(({ name }) => name === "apexlang-vocab-report.json")?.payload;
112
+ if (vocabularyReport?.blocking_reason === "UNSUPPORTED_MMD_VERSION") {
113
+ return { source: "unsupported-mmd" };
114
+ }
115
+
116
+ const findingKeys = new Set<string>();
117
+ const files = new Set<string>();
118
+ for (const { name, payload } of reports) {
119
+ for (const collection of [payload?.issues, payload?.unresolved]) {
120
+ if (!Array.isArray(collection)) continue;
121
+ collection.forEach((issue, index) => {
122
+ const identity = diagnosticIdentity(issue, name, index);
123
+ findingKeys.add(identity.key);
124
+ if (identity.file) files.add(identity.file);
125
+ });
126
+ }
127
+ }
128
+ if (
129
+ findingKeys.size >= MASS_VALIDATION_FINDING_THRESHOLD &&
130
+ files.size >= MASS_VALIDATION_DISTINCT_FILE_THRESHOLD
131
+ ) {
132
+ return {
133
+ source: "local-reports",
134
+ findingCount: findingKeys.size,
135
+ distinctFileCount: files.size
136
+ };
137
+ }
138
+ return undefined;
139
+ }
140
+
141
+ function detectCompilerTruthOutputSignal(output: string): ValidationCompatibilitySignal | undefined {
142
+ const findings = new Set<string>();
143
+ const files = new Set<string>();
144
+ for (const line of output.split(/\r?\n/)) {
145
+ const match = line.match(/^\s*-\s+(.+?\.apx):(\d+)(?::\d+)?:\s+([A-Z][A-Z0-9_]+)\b\s*(.*)$/);
146
+ if (!match?.[1]) continue;
147
+ findings.add(`${match[1]}:${match[2]}:${match[3]}:${match[4] ?? ""}`);
148
+ files.add(match[1]);
149
+ }
150
+ if (
151
+ findings.size >= MASS_VALIDATION_FINDING_THRESHOLD &&
152
+ files.size >= MASS_VALIDATION_DISTINCT_FILE_THRESHOLD
153
+ ) {
154
+ return {
155
+ source: "compiler-truth-output",
156
+ findingCount: findings.size,
157
+ distinctFileCount: files.size
158
+ };
159
+ }
160
+ return undefined;
161
+ }
162
+
163
+ export async function detectValidationCompatibilitySignal(
164
+ result: ApexlangRunResult
165
+ ): Promise<ValidationCompatibilitySignal | undefined> {
166
+ if (!VALIDATION_ACTIONS.has(result.action)) return undefined;
167
+
168
+ const payload = parseJsonRecord(result.stdout);
169
+ if (payload) {
170
+ const findingCount = maximumStructuredFindingCount(payload);
171
+ if (findingCount !== undefined && findingCount >= MASS_VALIDATION_FINDING_THRESHOLD) {
172
+ return { source: "structured-result", findingCount };
173
+ }
174
+ }
175
+ if (result.action === "local_validate") {
176
+ return detectLocalReportSignal(result.outputRoot);
177
+ }
178
+ if (result.action === "compiler_truth_audit") {
179
+ return detectCompilerTruthOutputSignal([result.stdout, result.stderr].filter(Boolean).join("\n"));
180
+ }
181
+ return undefined;
182
+ }
183
+
184
+ function tableCell(value: string): string {
185
+ return value.replaceAll("|", "\\|").replaceAll("\n", " ");
186
+ }
187
+
188
+ export function renderOrdsSqlclCompatibilityTable(): string {
189
+ const rows = ORDS_SQLCL_COMPATIBILITY_TABLE.map((row) => {
190
+ const guidance = row.diagnosticSqlclBuild && row.diagnosticSqlclDownloadUrl
191
+ ? `${row.sqlclGuidance} [Download ${row.diagnosticSqlclBuild}](${row.diagnosticSqlclDownloadUrl})`
192
+ : row.sqlclGuidance;
193
+ return `| ${tableCell(row.environment)} | ${tableCell(guidance)} | ${tableCell(row.basis)} |`;
194
+ });
195
+ return [
196
+ "| Server environment | SQLcl guidance | Basis |",
197
+ "| --- | --- | --- |",
198
+ ...rows
199
+ ].join("\n");
200
+ }
201
+
202
+ export function formatValidationCompatibilityAdvisory(
203
+ signal: ValidationCompatibilitySignal
204
+ ): string {
205
+ const findingSummary = signal.findingCount === undefined
206
+ ? "The application declares an unsupported APEXlang compiler metadata version."
207
+ : `Large-scale validation output detected (${signal.findingCount} findings${
208
+ signal.distinctFileCount === undefined ? "" : ` across ${signal.distinctFileCount} files`
209
+ }).`;
210
+ return [
211
+ "### SQLcl/ORDS compatibility advisory",
212
+ "",
213
+ `${findingSummary} Before changing many application files, check local \`sql -version\`, the app's \`.apex/apexlang.json\` \`mmdVersion\`, and the server APEX and ORDS versions with its administrator. A version/metadata mismatch can create broad diagnostic noise.`,
214
+ "",
215
+ renderOrdsSqlclCompatibilityTable(),
216
+ "",
217
+ compatibility.caveat,
218
+ "This advice does not turn a failed validation into a pass and does not authorize import."
219
+ ].join("\n");
220
+ }
221
+
222
+ export async function buildValidationCompatibilityAdvisory(
223
+ result: ApexlangRunResult
224
+ ): Promise<string> {
225
+ const signal = await detectValidationCompatibilitySignal(result);
226
+ return signal ? formatValidationCompatibilityAdvisory(signal) : "";
227
+ }
@@ -13,6 +13,18 @@ import {
13
13
  type ApexlangInput,
14
14
  type ApexlangRunResult
15
15
  } from "../lib/apexlang-cli.mjs";
16
+ import {
17
+ MASS_VALIDATION_DISTINCT_FILE_THRESHOLD,
18
+ MASS_VALIDATION_FINDING_THRESHOLD,
19
+ ORDS_SQLCL_COMPATIBILITY,
20
+ ORDS_SQLCL_COMPATIBILITY_GUIDELINE,
21
+ ORDS_SQLCL_COMPATIBILITY_TABLE,
22
+ buildValidationCompatibilityAdvisory,
23
+ clearLocalValidationCompatibilityReports,
24
+ detectValidationCompatibilitySignal,
25
+ formatValidationCompatibilityAdvisory,
26
+ renderOrdsSqlclCompatibilityTable
27
+ } from "./compatibility.ts";
16
28
 
17
29
  const MAX_TOOL_OUTPUT = 80_000;
18
30
  const COMMAND_TIMEOUT_MS = 10 * 60 * 1000;
@@ -77,14 +89,20 @@ function createNewTargetProved(result: ApexlangRunResult): boolean {
77
89
  payload?.failure_class === "create_new_confirmation_required";
78
90
  }
79
91
 
80
- function processOutput(result: ApexlangRunResult): string {
92
+ function processOutput(result: ApexlangRunResult, compatibilityAdvisory = ""): string {
81
93
  const streams = result.ok ? [result.stdout, result.stderr] : [result.stderr, result.stdout];
82
- return trimOutput(streams.filter(Boolean).join("\n").trim(), result.outputRoot);
94
+ const output = trimOutput(streams.filter(Boolean).join("\n").trim(), result.outputRoot);
95
+ return [output, compatibilityAdvisory].filter(Boolean).join("\n\n");
83
96
  }
84
97
 
85
- function failureOutput(result: ApexlangRunResult, fallback: string): string {
86
- const output = processOutput(result) || fallback;
87
- return `${output}\n\nAPEXlang reports: ${result.outputRoot}`;
98
+ function failureOutput(
99
+ result: ApexlangRunResult,
100
+ fallback: string,
101
+ compatibilityAdvisory = ""
102
+ ): string {
103
+ const streams = result.ok ? [result.stdout, result.stderr] : [result.stderr, result.stdout];
104
+ const output = trimOutput(streams.filter(Boolean).join("\n").trim(), result.outputRoot) || fallback;
105
+ return `${[output, compatibilityAdvisory].filter(Boolean).join("\n\n")}\n\nAPEXlang reports: ${result.outputRoot}`;
88
106
  }
89
107
 
90
108
  type ApexlangDependencies = {
@@ -113,6 +131,7 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
113
131
  "Load the apexlang skill before using the apexlang tool and follow its routing and Missing Inputs rules.",
114
132
  "Use apexlang workspace_probe before app-scoped APEXlang work.",
115
133
  EXPORT_OVERWRITE_GUIDELINE,
134
+ ORDS_SQLCL_COMPATIBILITY_GUIDELINE,
116
135
  "Use apexlang runtime_validate only after the user provides both db_connection_name and the matching APEX workspace_name; import requires the tool's separate post-check GUI choice."
117
136
  ],
118
137
  executionMode: "sequential",
@@ -194,11 +213,25 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
194
213
  ...(signal ? { signal } : {}),
195
214
  timeoutMs: COMMAND_TIMEOUT_MS
196
215
  };
216
+ if (input.action === "local_validate") {
217
+ await clearLocalValidationCompatibilityReports(outputRoot);
218
+ }
197
219
  const result = await dependencies.run(input, runOptions);
198
- const output = processOutput(result);
220
+ const compatibilityAdvisory = await buildValidationCompatibilityAdvisory(result);
221
+ if (compatibilityAdvisory) {
222
+ onUpdate?.({
223
+ content: [{ type: "text", text: compatibilityAdvisory }],
224
+ details: { action: input.action, compatibilityAdvisory: true }
225
+ });
226
+ }
227
+ const output = processOutput(result, compatibilityAdvisory);
199
228
  if (!result.ok) {
200
229
  throw new Error(
201
- failureOutput(result, `APEXlang ${input.action} failed with exit code ${result.code}.`)
230
+ failureOutput(
231
+ result,
232
+ `APEXlang ${input.action} failed with exit code ${result.code}.`,
233
+ compatibilityAdvisory
234
+ )
202
235
  );
203
236
  }
204
237
 
@@ -207,7 +240,8 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
207
240
  throw new Error(
208
241
  failureOutput(
209
242
  result,
210
- "APEXlang runtime validation did not produce authoritative live pass evidence."
243
+ "APEXlang runtime validation did not produce authoritative live pass evidence.",
244
+ compatibilityAdvisory
211
245
  )
212
246
  );
213
247
  }
@@ -299,10 +333,12 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
299
333
  expectedAppDigest
300
334
  });
301
335
  if (!createNewTargetProved(proofResult)) {
336
+ const proofCompatibilityAdvisory = await buildValidationCompatibilityAdvisory(proofResult);
302
337
  throw new Error(
303
338
  failureOutput(
304
339
  proofResult,
305
- "Oracle did not prove that the create-new target is absent from the selected workspace."
340
+ "Oracle did not prove that the create-new target is absent from the selected workspace.",
341
+ proofCompatibilityAdvisory
306
342
  )
307
343
  );
308
344
  }
@@ -343,12 +379,14 @@ export function createApexlangTool(overrides: Partial<ApexlangDependencies> = {}
343
379
  createNewConfirmed,
344
380
  expectedAppDigest
345
381
  });
346
- const importOutput = processOutput(importResult);
382
+ const importCompatibilityAdvisory = await buildValidationCompatibilityAdvisory(importResult);
383
+ const importOutput = processOutput(importResult, importCompatibilityAdvisory);
347
384
  if (!liveImportPassed(importResult)) {
348
385
  throw new Error(
349
386
  failureOutput(
350
387
  importResult,
351
- "APEXlang validate-and-import did not produce authoritative import pass evidence."
388
+ "APEXlang validate-and-import did not produce authoritative import pass evidence.",
389
+ importCompatibilityAdvisory
352
390
  )
353
391
  );
354
392
  }
@@ -429,11 +467,21 @@ export {
429
467
  IMPORT_CHOICE,
430
468
  CREATE_NEW_CHOICE,
431
469
  EXPORT_OVERWRITE_GUIDELINE,
470
+ MASS_VALIDATION_DISTINCT_FILE_THRESHOLD,
471
+ MASS_VALIDATION_FINDING_THRESHOLD,
472
+ ORDS_SQLCL_COMPATIBILITY,
473
+ ORDS_SQLCL_COMPATIBILITY_GUIDELINE,
474
+ ORDS_SQLCL_COMPATIBILITY_TABLE,
432
475
  UPDATE_EXISTING_CHOICE,
433
476
  actionWritesProject,
477
+ buildValidationCompatibilityAdvisory,
478
+ clearLocalValidationCompatibilityReports,
434
479
  confirmationMessage,
435
480
  createNewTargetProved,
481
+ detectValidationCompatibilitySignal,
482
+ formatValidationCompatibilityAdvisory,
436
483
  liveImportPassed,
437
- liveValidationPassed
484
+ liveValidationPassed,
485
+ renderOrdsSqlclCompatibilityTable
438
486
  };
439
487
  export type { ApexlangAction };
@@ -0,0 +1,67 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "policy": "advisory-only",
4
+ "lastReviewed": "2026-07-19",
5
+ "massValidation": {
6
+ "minimumFindings": 50,
7
+ "minimumDistinctFilesForAppWideReports": 5
8
+ },
9
+ "caveat": "Oracle publishes minimum APEXlang prerequisites, not an ORDS-to-SQLcl patch certification matrix. Exact SQLcl builds in this table are diagnostic baselines and never validation gates.",
10
+ "rows": [
11
+ {
12
+ "environment": "ORDS before 26.1.1 or APEX before 26.1",
13
+ "matchMode": "any",
14
+ "ordsRange": "<26.1.1",
15
+ "apexRange": "<26.1",
16
+ "sqlclGuidance": "APEXlang is unsupported; upgrade the server components before changing SQLcl.",
17
+ "diagnosticSqlclBuild": "",
18
+ "diagnosticSqlclDownloadUrl": "",
19
+ "basis": "oracle-confirmed",
20
+ "sourceUrls": [
21
+ "https://www.oracle.com/tools/ords/ords-relnotes-26.1.1.html",
22
+ "https://docs.oracle.com/en/database/oracle/apex/26.1/htmrn/changed-behavior.html"
23
+ ]
24
+ },
25
+ {
26
+ "environment": "APEX 26.1.x with ORDS 26.1.1 through 26.1.x",
27
+ "matchMode": "all",
28
+ "ordsRange": ">=26.1.1 <26.2.0",
29
+ "apexRange": "26.1.x",
30
+ "sqlclGuidance": "Oracle minimum: SQLcl 26.1. Diagnostic baseline: 26.1.2.132.1334.",
31
+ "diagnosticSqlclBuild": "26.1.2.132.1334",
32
+ "diagnosticSqlclDownloadUrl": "https://download.oracle.com/otn_software/java/sqldeveloper/sqlcl-26.1.2.132.1334.zip",
33
+ "basis": "oracle-minimum-plus-extension-advisory",
34
+ "sourceUrls": [
35
+ "https://docs.oracle.com/en/database/oracle/sql-developer-command-line/26.1/sqcug/prerequisites-apexlang.html",
36
+ "https://www.oracle.com/tools/sqlcl/sqlcl-relnotes-26.1.2.html"
37
+ ]
38
+ },
39
+ {
40
+ "environment": "APEX 26.1.x with ORDS 26.2.x",
41
+ "matchMode": "all",
42
+ "ordsRange": ">=26.2.0 <26.3.0",
43
+ "apexRange": "26.1.x",
44
+ "sqlclGuidance": "Oracle does not mandate SQLcl 26.2. On mass findings, compare with diagnostic baseline 26.1.2.132.1334.",
45
+ "diagnosticSqlclBuild": "26.1.2.132.1334",
46
+ "diagnosticSqlclDownloadUrl": "https://download.oracle.com/otn_software/java/sqldeveloper/sqlcl-26.1.2.132.1334.zip",
47
+ "basis": "extension-advisory",
48
+ "sourceUrls": [
49
+ "https://docs.oracle.com/en/database/oracle/sql-developer-command-line/26.1/sqcug/prerequisites-apexlang.html",
50
+ "https://www.oracle.com/tools/sqlcl/sqlcl-downloads.html"
51
+ ]
52
+ },
53
+ {
54
+ "environment": "Other or newer APEX, MMD, or ORDS release lines",
55
+ "matchMode": "fallback",
56
+ "ordsRange": "other",
57
+ "apexRange": "other",
58
+ "sqlclGuidance": "Verify current Oracle release documentation and use SQLcl compiler metadata that supports the app mmdVersion.",
59
+ "diagnosticSqlclBuild": "",
60
+ "diagnosticSqlclDownloadUrl": "",
61
+ "basis": "verify-current-docs",
62
+ "sourceUrls": [
63
+ "https://docs.oracle.com/en/database/oracle/apex/26.1/apxdc/using-sqlcl-apexlang.html"
64
+ ]
65
+ }
66
+ ]
67
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-apexlang",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "APEXlang support for pi, powered by Oracle's public APEXlang skill.",
5
5
  "type": "module",
6
6
  "license": "UPL-1.0",