@duckcodeailabs/dql-cli 1.13.3 → 1.13.4
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/dist/apps-api.d.ts +1 -0
- package/dist/apps-api.d.ts.map +1 -1
- package/dist/apps-api.js +31 -23
- package/dist/apps-api.js.map +1 -1
- package/dist/assets/dql-notebook/assets/{AgentLogPage-B3ugEb3H.js → AgentLogPage-DYmHO6_i.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AiBuildDialog-BK_TDNcM.js → AiBuildDialog-BfhaOd1h.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AiBuildResult-Cob_Lj05.js → AiBuildResult-DLKFAe6R.js} +3 -3
- package/dist/assets/dql-notebook/assets/{AiSidePanel-CzIgxmP9.js → AiSidePanel-C6Z3URGr.js} +1 -1
- package/dist/assets/dql-notebook/assets/{AnalyticsHome-C2vJ2fxY.js → AnalyticsHome-uG3xCP_s.js} +1 -1
- package/dist/assets/dql-notebook/assets/AppsView-DfieNjkh.js +5595 -0
- package/dist/assets/dql-notebook/assets/{BlockStudio-CaDNTKMM.js → BlockStudio-90J_wvWL.js} +12 -12
- package/dist/assets/dql-notebook/assets/{BusinessArtifactView-zwUOtddi.js → BusinessArtifactView-_zSMae5q.js} +1 -1
- package/dist/assets/dql-notebook/assets/{DbtFirstModelingPage-BlnhTMu3.js → DbtFirstModelingPage-DoXiPssu.js} +4 -4
- package/dist/assets/dql-notebook/assets/{GitPage-Coevr9NJ.js → GitPage-CUfAhS67.js} +3 -3
- package/dist/assets/dql-notebook/assets/{GlobalAiRail-BTZS11x5.js → GlobalAiRail-ovtL7nQu.js} +1 -1
- package/dist/assets/dql-notebook/assets/{GovernedContextPage-CjyyM_ne.js → GovernedContextPage-CaMiKAzA.js} +3 -3
- package/dist/assets/dql-notebook/assets/{HelpDocsPage-C1UeP85v.js → HelpDocsPage-CEGUx28b.js} +1 -1
- package/dist/assets/dql-notebook/assets/{HomePage-zGPFIvOY.js → HomePage-2v3SRf8V.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineageDAG-DbXnQWu3.js → LineageDAG-AaqLEiBN.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineageDetailView-Ch1Db01I.js → LineageDetailView-CFc8pm91.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineageDrawer-DLxqJO6D.js → LineageDrawer-DOkFjPq-.js} +1 -1
- package/dist/assets/dql-notebook/assets/{LineagePathBreadcrumb-B2tNdkr_.js → LineagePathBreadcrumb-BrDwCuMs.js} +1 -1
- package/dist/assets/dql-notebook/assets/{MiniLineageGraph-0gY-ZwCy.js → MiniLineageGraph-CiHtQs3y.js} +1 -1
- package/dist/assets/dql-notebook/assets/{NewBlockModal-DKVkXD20.js → NewBlockModal-DAgJZbws.js} +1 -1
- package/dist/assets/dql-notebook/assets/{NewNotebookModal-BUIByvYT.js → NewNotebookModal-xjG7nZ3O.js} +1 -1
- package/dist/assets/dql-notebook/assets/{NotebookEditor-D2fIUxjE.js → NotebookEditor-CXZaKfYT.js} +1 -1
- package/dist/assets/dql-notebook/assets/{ReadinessPage-Ci4LyNiQ.js → ReadinessPage-MuJBFwwg.js} +1 -1
- package/dist/assets/dql-notebook/assets/{SetupOnboarding-BF7ai_0t.js → SetupOnboarding-vKFtKtjh.js} +1 -1
- package/dist/assets/dql-notebook/assets/{SkillsPage-BgYrgirJ.js → SkillsPage-DCFVOV5f.js} +1 -1
- package/dist/assets/dql-notebook/assets/{TrustBadge-Bob1Laiq.js → TrustBadge-TcwXFFHK.js} +1 -1
- package/dist/assets/dql-notebook/assets/{UnifiedAgentRunPanel-IxDUKSG8.js → UnifiedAgentRunPanel-Cu-YgIe4.js} +1 -1
- package/dist/assets/dql-notebook/assets/{answer-to-notebook-Dk42N0pU.js → answer-to-notebook-DCFWlHB7.js} +1 -1
- package/dist/assets/dql-notebook/assets/{arrow-left-DKuuTw9l.js → arrow-left-BLnlJAtp.js} +1 -1
- package/dist/assets/dql-notebook/assets/{arrow-right-TH8_ufKG.js → arrow-right-BmUAb1aW.js} +1 -1
- package/dist/assets/dql-notebook/assets/{book-open-text-B-dcHHn0.js → book-open-text-bdSChSag.js} +1 -1
- package/dist/assets/dql-notebook/assets/{circle-x-BOc2KCZQ.js → circle-x-Cc6dEaf4.js} +1 -1
- package/dist/assets/dql-notebook/assets/{dagre.esm-CPT_vn5p.js → dagre.esm-CPebQKQ9.js} +1 -1
- package/dist/assets/dql-notebook/assets/{external-link-DtOfpYc6.js → external-link-rmXvubf3.js} +1 -1
- package/dist/assets/dql-notebook/assets/{grip-vertical-B8joDDH9.js → grip-vertical-Sg4zd5-Q.js} +1 -1
- package/dist/assets/dql-notebook/assets/{index-DJRMz64S.js → index-mQd_pC-P.js} +152 -152
- package/dist/assets/dql-notebook/assets/{link-2-DMZPHawg.js → link-2-BLaPoFxW.js} +1 -1
- package/dist/assets/dql-notebook/assets/{list-tree-Dw0qlxPK.js → list-tree-j0s4asFK.js} +1 -1
- package/dist/assets/dql-notebook/assets/{minimize-2-DUiSrPS3.js → minimize-2-Cl4pef4s.js} +1 -1
- package/dist/assets/dql-notebook/assets/{panel-right-open-BrrFrRZQ.js → panel-right-open-Clz-FtWi.js} +1 -1
- package/dist/assets/dql-notebook/assets/{play-Ced0HT9g.js → play-DFdazMg7.js} +1 -1
- package/dist/assets/dql-notebook/assets/{rotate-ccw-D_9U9o7X.js → rotate-ccw-C3tTaR7s.js} +1 -1
- package/dist/assets/dql-notebook/assets/{semantic-fields-BlDOaonV.js → semantic-fields-DIAhTlfy.js} +1 -1
- package/dist/assets/dql-notebook/assets/{sliders-horizontal-BDt6KRGR.js → sliders-horizontal-BUiu2tfY.js} +1 -1
- package/dist/assets/dql-notebook/assets/{star-CxUbF_BW.js → star--Yq77aH4.js} +1 -1
- package/dist/assets/dql-notebook/assets/{triangle-alert-COWnsSdh.js → triangle-alert-D5Ng-xZO.js} +1 -1
- package/dist/assets/dql-notebook/assets/{upload-DSFC2kJX.js → upload-L8BKQAxP.js} +1 -1
- package/dist/assets/dql-notebook/assets/{usePersistedAgentThreadId-DYdx896E.js → usePersistedAgentThreadId-DBu97YaM.js} +1 -1
- package/dist/assets/dql-notebook/assets/{user-round-Bfu7fosn.js → user-round-BK5N1cJW.js} +1 -1
- package/dist/assets/dql-notebook/assets/{wand-sparkles-DSpG0c0j.js → wand-sparkles-D8XDQD9z.js} +1 -1
- package/dist/assets/dql-notebook/assets/{workflow-B1_pj9gq.js → workflow-Bl9zwG0q.js} +1 -1
- package/dist/assets/dql-notebook/assets/{wrench-CvfM03KZ.js → wrench-C-zLCMbW.js} +1 -1
- package/dist/assets/dql-notebook/assets/{x-B4coLiOl.js → x-stiJ-sP7.js} +1 -1
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/local-operation-coordinator.d.ts.map +1 -1
- package/dist/local-operation-coordinator.js +16 -2
- package/dist/local-operation-coordinator.js.map +1 -1
- package/dist/local-runtime.d.ts +8 -0
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +83 -15
- package/dist/local-runtime.js.map +1 -1
- package/dist/package.json +10 -10
- package/package.json +10 -10
- package/dist/assets/dql-notebook/assets/AppsView-DEWQ0sHT.js +0 -5588
package/dist/local-runtime.js
CHANGED
|
@@ -48,6 +48,7 @@ import { buildSemanticTargetBinding } from './semantic-execution/target-binding.
|
|
|
48
48
|
import { discoverWarehouseMetadataScopes, normalizeConnectionMetadataScope, syncWarehouseMetadata, warehouseMetadataStatus, } from './warehouse-metadata.js';
|
|
49
49
|
import { NotebookDatasetWorkspace, } from "./notebook-datasets.js";
|
|
50
50
|
import { prepareBlockInvocation } from './block-invocation.js';
|
|
51
|
+
export const APP_SOURCE_REUSABLE_TAG = 'app-source';
|
|
51
52
|
const NOTEBOOK_EXECUTE_PREVIEW_ROW_LIMIT = 500;
|
|
52
53
|
const NOTEBOOK_FAVICON_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="7" fill="#6d5dfc"/><path d="M9 9h14v14H9z" fill="none" stroke="#fff" stroke-width="2"/><path d="M13 13h6M13 17h6M13 21h4" stroke="#fff" stroke-width="2" stroke-linecap="round"/></svg>';
|
|
53
54
|
export function resolveProjectSemanticConfig(projectConfig, projectRoot) {
|
|
@@ -5809,10 +5810,20 @@ export async function startLocalServer(opts) {
|
|
|
5809
5810
|
};
|
|
5810
5811
|
};
|
|
5811
5812
|
const certifyBlockStudioSource = async (source, blockPath, options = {}) => {
|
|
5813
|
+
options.reportProgress?.({
|
|
5814
|
+
phase: 'validating',
|
|
5815
|
+
progress: 10,
|
|
5816
|
+
message: 'Validating the saved DQL source.',
|
|
5817
|
+
});
|
|
5812
5818
|
let validation = validateBlockStudioSource(source, semanticLayer);
|
|
5813
5819
|
let preview = null;
|
|
5814
5820
|
let testResults = null;
|
|
5815
5821
|
const blockers = [];
|
|
5822
|
+
options.reportProgress?.({
|
|
5823
|
+
phase: 'previewing',
|
|
5824
|
+
progress: 30,
|
|
5825
|
+
message: 'Compiling and previewing the saved block.',
|
|
5826
|
+
});
|
|
5816
5827
|
try {
|
|
5817
5828
|
preview = await runBlockStudioPreviewSource(source);
|
|
5818
5829
|
validation = preview.validation;
|
|
@@ -5820,6 +5831,11 @@ export async function startLocalServer(opts) {
|
|
|
5820
5831
|
catch (error) {
|
|
5821
5832
|
blockers.push(error instanceof Error ? error.message : String(error));
|
|
5822
5833
|
}
|
|
5834
|
+
options.reportProgress?.({
|
|
5835
|
+
phase: 'testing',
|
|
5836
|
+
progress: 60,
|
|
5837
|
+
message: 'Evaluating declared block tests.',
|
|
5838
|
+
});
|
|
5823
5839
|
try {
|
|
5824
5840
|
testResults = preview
|
|
5825
5841
|
? await runBlockStudioTestSummary(source, undefined, preview)
|
|
@@ -5835,6 +5851,11 @@ export async function startLocalServer(opts) {
|
|
|
5835
5851
|
runAt: new Date(),
|
|
5836
5852
|
};
|
|
5837
5853
|
}
|
|
5854
|
+
options.reportProgress?.({
|
|
5855
|
+
phase: 'assessing',
|
|
5856
|
+
progress: 75,
|
|
5857
|
+
message: 'Assessing certification rules and evidence.',
|
|
5858
|
+
});
|
|
5838
5859
|
const parsed = parseBlockSourceMetadata(source);
|
|
5839
5860
|
const record = {
|
|
5840
5861
|
id: parsed.name || 'local',
|
|
@@ -11689,7 +11710,7 @@ export async function startLocalServer(opts) {
|
|
|
11689
11710
|
return;
|
|
11690
11711
|
}
|
|
11691
11712
|
}
|
|
11692
|
-
const draftSource = setBlockStudioStatusInSource(source, 'draft');
|
|
11713
|
+
const draftSource = markBlockStudioSourceReusable(setBlockStudioStatusInSource(source, 'draft'));
|
|
11693
11714
|
const parsed = parseBlockSourceMetadata(draftSource);
|
|
11694
11715
|
const name = typeof suppliedMetadata.name === 'string' && suppliedMetadata.name.trim()
|
|
11695
11716
|
? suppliedMetadata.name.trim()
|
|
@@ -11710,7 +11731,10 @@ export async function startLocalServer(opts) {
|
|
|
11710
11731
|
domain: typeof suppliedMetadata.domain === 'string' ? suppliedMetadata.domain : parsed.domain,
|
|
11711
11732
|
description: typeof suppliedMetadata.description === 'string' ? suppliedMetadata.description : parsed.description,
|
|
11712
11733
|
owner: typeof suppliedMetadata.owner === 'string' ? suppliedMetadata.owner : parsed.owner,
|
|
11713
|
-
tags: Array.
|
|
11734
|
+
tags: Array.from(new Set([
|
|
11735
|
+
...(Array.isArray(suppliedMetadata.tags) ? suppliedMetadata.tags.map(String) : parsed.tags),
|
|
11736
|
+
APP_SOURCE_REUSABLE_TAG,
|
|
11737
|
+
])),
|
|
11714
11738
|
lineage: Array.isArray(suppliedMetadata.lineage) ? suppliedMetadata.lineage.map(String) : undefined,
|
|
11715
11739
|
};
|
|
11716
11740
|
// A saved draft already has a durable identity, even when it lives in
|
|
@@ -11747,8 +11771,14 @@ export async function startLocalServer(opts) {
|
|
|
11747
11771
|
}
|
|
11748
11772
|
}
|
|
11749
11773
|
operationCoordinator.run(operation.id, async (signal, report) => {
|
|
11750
|
-
|
|
11751
|
-
|
|
11774
|
+
const result = await certifyBlockStudioSource(draftSource, draftPath, {
|
|
11775
|
+
enterprise: body.enterprise === true,
|
|
11776
|
+
reportProgress: (progress) => {
|
|
11777
|
+
if (signal.aborted)
|
|
11778
|
+
throw Object.assign(new Error('Certification cancelled.'), { code: 'OPERATION_CANCELLED' });
|
|
11779
|
+
report(progress);
|
|
11780
|
+
},
|
|
11781
|
+
});
|
|
11752
11782
|
const blockers = Array.from(new Set(result.checklist.blockers));
|
|
11753
11783
|
if (signal.aborted)
|
|
11754
11784
|
throw Object.assign(new Error('Certification cancelled.'), { code: 'OPERATION_CANCELLED' });
|
|
@@ -11771,7 +11801,7 @@ export async function startLocalServer(opts) {
|
|
|
11771
11801
|
block: { ...openedDraft, validation: result.validation },
|
|
11772
11802
|
};
|
|
11773
11803
|
}
|
|
11774
|
-
report({ phase: 'publishing', progress:
|
|
11804
|
+
report({ phase: 'publishing', progress: 82, message: 'Publishing the certified block.' });
|
|
11775
11805
|
const certifiedSource = setBlockStudioStatusInSource(draftSource, 'certified');
|
|
11776
11806
|
const certifiedMetadata = parseBlockSourceMetadata(certifiedSource);
|
|
11777
11807
|
const savedPath = saveBlockStudioArtifacts(projectRoot, {
|
|
@@ -11813,7 +11843,9 @@ export async function startLocalServer(opts) {
|
|
|
11813
11843
|
catch {
|
|
11814
11844
|
/* best-effort: learning capture must never block certification */
|
|
11815
11845
|
}
|
|
11846
|
+
report({ phase: 'indexing', progress: 92, message: 'Queueing the certified source index refresh.' });
|
|
11816
11847
|
const refreshOperation = scheduleProjectRefresh('block-studio-certification');
|
|
11848
|
+
report({ phase: 'indexing', progress: 96, message: 'Certified source saved; index refresh queued.' });
|
|
11817
11849
|
if (result.preview)
|
|
11818
11850
|
writeBlockStudioRunSummary(projectRoot, savedPath, certifiedSource, result.preview.result);
|
|
11819
11851
|
const openedCertified = openBlockStudioDocument(projectRoot, savedPath, semanticLayer);
|
|
@@ -12493,13 +12525,14 @@ export async function startLocalServer(opts) {
|
|
|
12493
12525
|
}));
|
|
12494
12526
|
return;
|
|
12495
12527
|
}
|
|
12528
|
+
const reusableSource = markBlockStudioSourceReusable(readiness.candidate.dqlSource);
|
|
12496
12529
|
const savedPath = saveBlockStudioArtifacts(projectRoot, {
|
|
12497
|
-
source:
|
|
12530
|
+
source: reusableSource,
|
|
12498
12531
|
name: readiness.candidate.name,
|
|
12499
12532
|
domain: readiness.candidate.domain,
|
|
12500
12533
|
description: readiness.candidate.description,
|
|
12501
12534
|
owner: readiness.candidate.owner,
|
|
12502
|
-
tags: readiness.candidate.tags,
|
|
12535
|
+
tags: Array.from(new Set([...readiness.candidate.tags, APP_SOURCE_REUSABLE_TAG])),
|
|
12503
12536
|
lineage: readiness.candidate.lineage.sourceTables,
|
|
12504
12537
|
importMeta: {
|
|
12505
12538
|
importId,
|
|
@@ -12508,7 +12541,13 @@ export async function startLocalServer(opts) {
|
|
|
12508
12541
|
sourcePath: readiness.candidate.sourcePath,
|
|
12509
12542
|
},
|
|
12510
12543
|
});
|
|
12511
|
-
const next = {
|
|
12544
|
+
const next = {
|
|
12545
|
+
...readiness.candidate,
|
|
12546
|
+
dqlSource: reusableSource,
|
|
12547
|
+
tags: Array.from(new Set([...readiness.candidate.tags, APP_SOURCE_REUSABLE_TAG])),
|
|
12548
|
+
reviewStatus: 'saved',
|
|
12549
|
+
savedPath,
|
|
12550
|
+
};
|
|
12512
12551
|
writeBlockStudioImportCandidate(projectRoot, importId, next);
|
|
12513
12552
|
await refreshLocalMetadataCatalog(projectRoot);
|
|
12514
12553
|
const payload = openBlockStudioDocument(projectRoot, savedPath, semanticLayer);
|
|
@@ -12751,7 +12790,7 @@ export async function startLocalServer(opts) {
|
|
|
12751
12790
|
try {
|
|
12752
12791
|
const body = await readJSON(req);
|
|
12753
12792
|
const source = typeof body.source === 'string'
|
|
12754
|
-
? sanitizeAgentBlockDraftSource(body.source)
|
|
12793
|
+
? markBlockStudioSourceReusable(sanitizeAgentBlockDraftSource(body.source))
|
|
12755
12794
|
: '';
|
|
12756
12795
|
const name = typeof body.name === 'string' ? body.name.trim() : '';
|
|
12757
12796
|
if (!source.trim() || !name) {
|
|
@@ -12764,7 +12803,10 @@ export async function startLocalServer(opts) {
|
|
|
12764
12803
|
name,
|
|
12765
12804
|
domain: typeof body.domain === 'string' ? body.domain : undefined,
|
|
12766
12805
|
description: typeof body.description === 'string' ? body.description : undefined,
|
|
12767
|
-
tags: Array.
|
|
12806
|
+
tags: Array.from(new Set([
|
|
12807
|
+
...(Array.isArray(body.tags) ? body.tags.map(String) : ['ai-generated', 'review-required']),
|
|
12808
|
+
APP_SOURCE_REUSABLE_TAG,
|
|
12809
|
+
])),
|
|
12768
12810
|
stableSuffix: typeof body.runId === 'string' ? body.runId : undefined,
|
|
12769
12811
|
});
|
|
12770
12812
|
const payload = openBlockStudioDocument(projectRoot, savedPath, semanticLayer);
|
|
@@ -12780,7 +12822,9 @@ export async function startLocalServer(opts) {
|
|
|
12780
12822
|
if (req.method === 'POST' && path === '/api/block-studio/save') {
|
|
12781
12823
|
try {
|
|
12782
12824
|
const body = await readJSON(req);
|
|
12783
|
-
const source = typeof body.source === 'string'
|
|
12825
|
+
const source = typeof body.source === 'string'
|
|
12826
|
+
? markBlockStudioSourceReusable(body.source)
|
|
12827
|
+
: '';
|
|
12784
12828
|
const metadata = body.metadata && typeof body.metadata === 'object'
|
|
12785
12829
|
? body.metadata
|
|
12786
12830
|
: {};
|
|
@@ -12817,7 +12861,10 @@ export async function startLocalServer(opts) {
|
|
|
12817
12861
|
folderPath: metadata.folderPath,
|
|
12818
12862
|
description: metadata.description,
|
|
12819
12863
|
owner: metadata.owner,
|
|
12820
|
-
tags: Array.
|
|
12864
|
+
tags: Array.from(new Set([
|
|
12865
|
+
...(Array.isArray(metadata.tags) ? metadata.tags.map(String) : []),
|
|
12866
|
+
APP_SOURCE_REUSABLE_TAG,
|
|
12867
|
+
])),
|
|
12821
12868
|
lineage: Array.isArray(metadata.lineage) ? metadata.lineage.map(String) : undefined,
|
|
12822
12869
|
importMeta: metadata.sourceKind || metadata.sourcePath || metadata.importId || metadata.candidateId
|
|
12823
12870
|
? {
|
|
@@ -21745,14 +21792,18 @@ export function validateBlockStudioSource(source, semanticLayer) {
|
|
|
21745
21792
|
};
|
|
21746
21793
|
}
|
|
21747
21794
|
export async function createDqlArtifactGenerationSessionForProject(projectRoot, options, semanticLayer) {
|
|
21748
|
-
const
|
|
21749
|
-
if (!
|
|
21795
|
+
const normalizedDqlArtifact = normalizeDqlArtifactReference(options.dqlArtifact);
|
|
21796
|
+
if (!normalizedDqlArtifact)
|
|
21750
21797
|
throw new Error('A DQL artifact with source is required for DQL draft promotion.');
|
|
21798
|
+
const dqlArtifact = {
|
|
21799
|
+
...normalizedDqlArtifact,
|
|
21800
|
+
source: markBlockStudioSourceReusable(normalizedDqlArtifact.source),
|
|
21801
|
+
};
|
|
21751
21802
|
const question = notebookResearchString(options.question) ?? dqlArtifact.name ?? 'Generated DQL artifact';
|
|
21752
21803
|
const slug = deriveGeneratedDraftSlug(dqlArtifact.name ?? question);
|
|
21753
21804
|
const domain = notebookResearchString(options.domain) ?? 'misc';
|
|
21754
21805
|
const owner = notebookResearchString(options.owner) ?? '';
|
|
21755
|
-
const tags = Array.from(new Set(['notebook-research', 'review-required', 'dql-artifact', ...(Array.isArray(options.tags) ? options.tags : [])]
|
|
21806
|
+
const tags = Array.from(new Set(['notebook-research', 'review-required', 'dql-artifact', APP_SOURCE_REUSABLE_TAG, ...(Array.isArray(options.tags) ? options.tags : [])]
|
|
21756
21807
|
.map((tag) => notebookResearchString(tag))
|
|
21757
21808
|
.filter((tag) => Boolean(tag))));
|
|
21758
21809
|
const proposedContractId = `${domain}.Unknown.${slug}`;
|
|
@@ -22646,6 +22697,23 @@ export function parseBlockSourceMetadata(source) {
|
|
|
22646
22697
|
metricsRef: extractStringArray('metrics'),
|
|
22647
22698
|
};
|
|
22648
22699
|
}
|
|
22700
|
+
/**
|
|
22701
|
+
* Persist the explicit App-source reuse decision in canonical DQL. Generated
|
|
22702
|
+
* execution stays transient; only Block Studio save/promotion routes call this
|
|
22703
|
+
* helper. The marker is a normal parser-supported tag, so refresh/reindex can
|
|
22704
|
+
* make the participation decision without relying on filenames or prose.
|
|
22705
|
+
*/
|
|
22706
|
+
export function markBlockStudioSourceReusable(source) {
|
|
22707
|
+
const parsed = parseBlockSourceMetadata(source);
|
|
22708
|
+
if (parsed.tags.some((tag) => tag.trim().toLowerCase() === APP_SOURCE_REUSABLE_TAG))
|
|
22709
|
+
return source;
|
|
22710
|
+
const tags = Array.from(new Set([...parsed.tags, APP_SOURCE_REUSABLE_TAG]));
|
|
22711
|
+
const rendered = tags.map((tag) => JSON.stringify(tag)).join(', ');
|
|
22712
|
+
if (/\btags\s*=\s*\[[\s\S]*?\]/i.test(source)) {
|
|
22713
|
+
return source.replace(/\btags\s*=\s*\[[\s\S]*?\]/i, `tags = [${rendered}]`);
|
|
22714
|
+
}
|
|
22715
|
+
return source.replace(/(\bblock\s+"[^"]+"\s*\{)/i, `$1\n tags = [${rendered}]`);
|
|
22716
|
+
}
|
|
22649
22717
|
function compareBlockStudioValues(actual, operator, expected) {
|
|
22650
22718
|
const expectedValue = normalizeBlockStudioExpected(expected);
|
|
22651
22719
|
if (operator === '==' || operator === '=')
|