@pgpmjs/core 7.28.0 → 7.30.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/core/template-scaffold.d.ts +32 -0
- package/core/template-scaffold.js +149 -0
- package/esm/core/template-scaffold.js +147 -1
- package/package.json +14 -14
|
@@ -103,5 +103,37 @@ export type TemplateRepoFlavor = keyof typeof TEMPLATE_REPOS;
|
|
|
103
103
|
export declare const DEFAULT_TEMPLATE_REPO: "https://github.com/constructive-io/pgpm-boilerplates.git";
|
|
104
104
|
export declare const DEFAULT_TEMPLATE_TTL_MS: number;
|
|
105
105
|
export declare const DEFAULT_TEMPLATE_TOOL_NAME = "pgpm";
|
|
106
|
+
export interface TemplateSourceInfo {
|
|
107
|
+
repo: string;
|
|
108
|
+
branch?: string;
|
|
109
|
+
remoteSha?: string;
|
|
110
|
+
refreshed: boolean;
|
|
111
|
+
offline: boolean;
|
|
112
|
+
local: boolean;
|
|
113
|
+
}
|
|
114
|
+
export interface RefreshTemplateCacheOptions {
|
|
115
|
+
templateRepo?: string;
|
|
116
|
+
branch?: string;
|
|
117
|
+
toolName?: string;
|
|
118
|
+
cacheBaseDir?: string;
|
|
119
|
+
cwd?: string;
|
|
120
|
+
force?: boolean;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Clear the per-process refresh memo. Primarily useful for tests and callers
|
|
124
|
+
* that begin a new init run in the same process.
|
|
125
|
+
*/
|
|
126
|
+
export declare function _resetTemplateRefreshMemo(): void;
|
|
127
|
+
/**
|
|
128
|
+
* Check the remote template revision and clear a stale local clone.
|
|
129
|
+
*
|
|
130
|
+
* Set PGPM_TEMPLATE_OFFLINE to skip `git ls-remote`, which is useful for tests
|
|
131
|
+
* and environments that must not make network requests.
|
|
132
|
+
*/
|
|
133
|
+
export declare function refreshTemplateCache(options?: RefreshTemplateCacheOptions): TemplateSourceInfo;
|
|
134
|
+
export declare function describeTemplateSource(info: TemplateSourceInfo, opts?: {
|
|
135
|
+
toolName?: string;
|
|
136
|
+
cacheBaseDir?: string;
|
|
137
|
+
}): string;
|
|
106
138
|
export declare function inspectTemplate(options: InspectTemplateOptions): InspectTemplateResult;
|
|
107
139
|
export declare function scaffoldTemplate(options: ScaffoldTemplateOptions): Promise<ScaffoldTemplateResult>;
|
|
@@ -4,8 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.DEFAULT_TEMPLATE_TOOL_NAME = exports.DEFAULT_TEMPLATE_TTL_MS = exports.DEFAULT_TEMPLATE_REPO = exports.TEMPLATE_REPOS = exports.SkillInstaller = void 0;
|
|
7
|
+
exports._resetTemplateRefreshMemo = _resetTemplateRefreshMemo;
|
|
8
|
+
exports.refreshTemplateCache = refreshTemplateCache;
|
|
9
|
+
exports.describeTemplateSource = describeTemplateSource;
|
|
7
10
|
exports.inspectTemplate = inspectTemplate;
|
|
8
11
|
exports.scaffoldTemplate = scaffoldTemplate;
|
|
12
|
+
const child_process_1 = require("child_process");
|
|
13
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
14
|
const genomic_1 = require("genomic");
|
|
10
15
|
const os_1 = __importDefault(require("os"));
|
|
11
16
|
const path_1 = __importDefault(require("path"));
|
|
@@ -35,6 +40,150 @@ function resolveCacheBaseDir(cacheBaseDir) {
|
|
|
35
40
|
}
|
|
36
41
|
return undefined;
|
|
37
42
|
}
|
|
43
|
+
const templateRefreshMemo = new Map();
|
|
44
|
+
/**
|
|
45
|
+
* Clear the per-process refresh memo. Primarily useful for tests and callers
|
|
46
|
+
* that begin a new init run in the same process.
|
|
47
|
+
*/
|
|
48
|
+
function _resetTemplateRefreshMemo() {
|
|
49
|
+
templateRefreshMemo.clear();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check the remote template revision and clear a stale local clone.
|
|
53
|
+
*
|
|
54
|
+
* Set PGPM_TEMPLATE_OFFLINE to skip `git ls-remote`, which is useful for tests
|
|
55
|
+
* and environments that must not make network requests.
|
|
56
|
+
*/
|
|
57
|
+
function refreshTemplateCache(options = {}) {
|
|
58
|
+
const { templateRepo = exports.DEFAULT_TEMPLATE_REPO, branch, toolName = exports.DEFAULT_TEMPLATE_TOOL_NAME, cacheBaseDir, cwd, force = false, } = options;
|
|
59
|
+
const template = templateRepo.startsWith('.') ||
|
|
60
|
+
templateRepo.startsWith('/') ||
|
|
61
|
+
templateRepo.startsWith('~')
|
|
62
|
+
? path_1.default.resolve(cwd ?? process.cwd(), templateRepo)
|
|
63
|
+
: templateRepo;
|
|
64
|
+
if (templateRepo.startsWith('.') ||
|
|
65
|
+
templateRepo.startsWith('/') ||
|
|
66
|
+
templateRepo.startsWith('~')) {
|
|
67
|
+
return {
|
|
68
|
+
repo: template,
|
|
69
|
+
branch,
|
|
70
|
+
refreshed: false,
|
|
71
|
+
offline: false,
|
|
72
|
+
local: true,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const url = new genomic_1.GitCloner().normalizeUrl(templateRepo);
|
|
76
|
+
const cm = new genomic_1.CacheManager({
|
|
77
|
+
toolName,
|
|
78
|
+
baseDir: resolveCacheBaseDir(cacheBaseDir),
|
|
79
|
+
});
|
|
80
|
+
const key = cm.createKey(url, branch);
|
|
81
|
+
const memoKey = `${key}|${force}`;
|
|
82
|
+
const memoized = templateRefreshMemo.get(memoKey);
|
|
83
|
+
if (memoized)
|
|
84
|
+
return memoized;
|
|
85
|
+
if (process.env.PGPM_TEMPLATE_OFFLINE) {
|
|
86
|
+
const info = {
|
|
87
|
+
repo: url,
|
|
88
|
+
branch,
|
|
89
|
+
refreshed: false,
|
|
90
|
+
offline: true,
|
|
91
|
+
local: false,
|
|
92
|
+
};
|
|
93
|
+
templateRefreshMemo.set(memoKey, info);
|
|
94
|
+
return info;
|
|
95
|
+
}
|
|
96
|
+
let remoteSha;
|
|
97
|
+
try {
|
|
98
|
+
const output = (0, child_process_1.execFileSync)('git', ['ls-remote', '--', url, branch ?? 'HEAD'], { stdio: 'pipe', encoding: 'utf-8', timeout: 15_000 });
|
|
99
|
+
const match = output.match(/\b([0-9a-f]{40})\b/i);
|
|
100
|
+
if (!match)
|
|
101
|
+
throw new Error('git ls-remote returned no commit SHA');
|
|
102
|
+
remoteSha = match[1];
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
const info = {
|
|
106
|
+
repo: url,
|
|
107
|
+
branch,
|
|
108
|
+
refreshed: false,
|
|
109
|
+
offline: true,
|
|
110
|
+
local: false,
|
|
111
|
+
};
|
|
112
|
+
templateRefreshMemo.set(memoKey, info);
|
|
113
|
+
return info;
|
|
114
|
+
}
|
|
115
|
+
const refPath = path_1.default.join(cm.getMetadataDir(), `${key}.ref.json`);
|
|
116
|
+
let previousSha;
|
|
117
|
+
try {
|
|
118
|
+
const ref = JSON.parse(fs_1.default.readFileSync(refPath, 'utf8'));
|
|
119
|
+
previousSha = typeof ref.sha === 'string' ? ref.sha : undefined;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// A missing or malformed sidecar is treated as unknown.
|
|
123
|
+
}
|
|
124
|
+
const cachePath = path_1.default.join(cm.getReposDir(), key);
|
|
125
|
+
const refreshed = force ||
|
|
126
|
+
previousSha !== remoteSha ||
|
|
127
|
+
(fs_1.default.existsSync(cachePath) && !previousSha);
|
|
128
|
+
if (refreshed)
|
|
129
|
+
cm.clear(key);
|
|
130
|
+
fs_1.default.mkdirSync(cm.getMetadataDir(), { recursive: true });
|
|
131
|
+
fs_1.default.writeFileSync(refPath, JSON.stringify({ sha: remoteSha, checkedAt: Date.now() }, null, 2));
|
|
132
|
+
const info = {
|
|
133
|
+
repo: url,
|
|
134
|
+
branch,
|
|
135
|
+
remoteSha,
|
|
136
|
+
refreshed,
|
|
137
|
+
offline: false,
|
|
138
|
+
local: false,
|
|
139
|
+
};
|
|
140
|
+
templateRefreshMemo.set(memoKey, info);
|
|
141
|
+
return info;
|
|
142
|
+
}
|
|
143
|
+
function formatAge(lastUpdated) {
|
|
144
|
+
const seconds = Math.max(0, Math.floor((Date.now() - lastUpdated) / 1000));
|
|
145
|
+
if (seconds < 60)
|
|
146
|
+
return `${seconds}s`;
|
|
147
|
+
const minutes = Math.floor(seconds / 60);
|
|
148
|
+
if (minutes < 60)
|
|
149
|
+
return `${minutes}m`;
|
|
150
|
+
const hours = Math.floor(minutes / 60);
|
|
151
|
+
if (hours < 24)
|
|
152
|
+
return `${hours}h`;
|
|
153
|
+
return `${Math.floor(hours / 24)}d`;
|
|
154
|
+
}
|
|
155
|
+
function describeTemplateSource(info, opts = {}) {
|
|
156
|
+
if (info.local)
|
|
157
|
+
return `using local template ${info.repo}`;
|
|
158
|
+
const repoDisplay = info.repo
|
|
159
|
+
.replace(/^https:\/\/github\.com\//, '')
|
|
160
|
+
.replace(/\.git$/, '');
|
|
161
|
+
const label = `${repoDisplay}@${info.branch ?? 'HEAD'}`;
|
|
162
|
+
const shortSha = info.remoteSha?.slice(0, 7);
|
|
163
|
+
let fetched;
|
|
164
|
+
if (info.refreshed) {
|
|
165
|
+
fetched = 'fetched just now';
|
|
166
|
+
}
|
|
167
|
+
else if (info.remoteSha) {
|
|
168
|
+
const url = new genomic_1.GitCloner().normalizeUrl(info.repo);
|
|
169
|
+
const cm = new genomic_1.CacheManager({
|
|
170
|
+
toolName: opts.toolName ?? exports.DEFAULT_TEMPLATE_TOOL_NAME,
|
|
171
|
+
baseDir: resolveCacheBaseDir(opts.cacheBaseDir),
|
|
172
|
+
});
|
|
173
|
+
const key = cm.createKey(url, info.branch);
|
|
174
|
+
const metadata = cm.getMetadata(key);
|
|
175
|
+
if (metadata?.lastUpdated)
|
|
176
|
+
fetched = `fetched ${formatAge(metadata.lastUpdated)} ago`;
|
|
177
|
+
}
|
|
178
|
+
const details = [
|
|
179
|
+
shortSha,
|
|
180
|
+
fetched,
|
|
181
|
+
].filter(Boolean).join(', ');
|
|
182
|
+
let result = `using ${label}${details ? ` (${details})` : ''}`;
|
|
183
|
+
if (info.offline)
|
|
184
|
+
result += ' (offline, using cached copy)';
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
38
187
|
function inspectTemplate(options) {
|
|
39
188
|
const { fromPath, templateRepo = exports.DEFAULT_TEMPLATE_REPO, branch, cacheTtlMs = exports.DEFAULT_TEMPLATE_TTL_MS, toolName = exports.DEFAULT_TEMPLATE_TOOL_NAME, cwd, cacheBaseDir, dir, } = options;
|
|
40
189
|
const scaffolder = new genomic_1.TemplateScaffolder({
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { CacheManager, GitCloner, TemplateScaffolder } from 'genomic';
|
|
2
4
|
import os from 'os';
|
|
3
5
|
import path from 'path';
|
|
4
6
|
export { SkillInstaller } from 'genomic';
|
|
@@ -26,6 +28,150 @@ function resolveCacheBaseDir(cacheBaseDir) {
|
|
|
26
28
|
}
|
|
27
29
|
return undefined;
|
|
28
30
|
}
|
|
31
|
+
const templateRefreshMemo = new Map();
|
|
32
|
+
/**
|
|
33
|
+
* Clear the per-process refresh memo. Primarily useful for tests and callers
|
|
34
|
+
* that begin a new init run in the same process.
|
|
35
|
+
*/
|
|
36
|
+
export function _resetTemplateRefreshMemo() {
|
|
37
|
+
templateRefreshMemo.clear();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check the remote template revision and clear a stale local clone.
|
|
41
|
+
*
|
|
42
|
+
* Set PGPM_TEMPLATE_OFFLINE to skip `git ls-remote`, which is useful for tests
|
|
43
|
+
* and environments that must not make network requests.
|
|
44
|
+
*/
|
|
45
|
+
export function refreshTemplateCache(options = {}) {
|
|
46
|
+
const { templateRepo = DEFAULT_TEMPLATE_REPO, branch, toolName = DEFAULT_TEMPLATE_TOOL_NAME, cacheBaseDir, cwd, force = false, } = options;
|
|
47
|
+
const template = templateRepo.startsWith('.') ||
|
|
48
|
+
templateRepo.startsWith('/') ||
|
|
49
|
+
templateRepo.startsWith('~')
|
|
50
|
+
? path.resolve(cwd ?? process.cwd(), templateRepo)
|
|
51
|
+
: templateRepo;
|
|
52
|
+
if (templateRepo.startsWith('.') ||
|
|
53
|
+
templateRepo.startsWith('/') ||
|
|
54
|
+
templateRepo.startsWith('~')) {
|
|
55
|
+
return {
|
|
56
|
+
repo: template,
|
|
57
|
+
branch,
|
|
58
|
+
refreshed: false,
|
|
59
|
+
offline: false,
|
|
60
|
+
local: true,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const url = new GitCloner().normalizeUrl(templateRepo);
|
|
64
|
+
const cm = new CacheManager({
|
|
65
|
+
toolName,
|
|
66
|
+
baseDir: resolveCacheBaseDir(cacheBaseDir),
|
|
67
|
+
});
|
|
68
|
+
const key = cm.createKey(url, branch);
|
|
69
|
+
const memoKey = `${key}|${force}`;
|
|
70
|
+
const memoized = templateRefreshMemo.get(memoKey);
|
|
71
|
+
if (memoized)
|
|
72
|
+
return memoized;
|
|
73
|
+
if (process.env.PGPM_TEMPLATE_OFFLINE) {
|
|
74
|
+
const info = {
|
|
75
|
+
repo: url,
|
|
76
|
+
branch,
|
|
77
|
+
refreshed: false,
|
|
78
|
+
offline: true,
|
|
79
|
+
local: false,
|
|
80
|
+
};
|
|
81
|
+
templateRefreshMemo.set(memoKey, info);
|
|
82
|
+
return info;
|
|
83
|
+
}
|
|
84
|
+
let remoteSha;
|
|
85
|
+
try {
|
|
86
|
+
const output = execFileSync('git', ['ls-remote', '--', url, branch ?? 'HEAD'], { stdio: 'pipe', encoding: 'utf-8', timeout: 15_000 });
|
|
87
|
+
const match = output.match(/\b([0-9a-f]{40})\b/i);
|
|
88
|
+
if (!match)
|
|
89
|
+
throw new Error('git ls-remote returned no commit SHA');
|
|
90
|
+
remoteSha = match[1];
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
const info = {
|
|
94
|
+
repo: url,
|
|
95
|
+
branch,
|
|
96
|
+
refreshed: false,
|
|
97
|
+
offline: true,
|
|
98
|
+
local: false,
|
|
99
|
+
};
|
|
100
|
+
templateRefreshMemo.set(memoKey, info);
|
|
101
|
+
return info;
|
|
102
|
+
}
|
|
103
|
+
const refPath = path.join(cm.getMetadataDir(), `${key}.ref.json`);
|
|
104
|
+
let previousSha;
|
|
105
|
+
try {
|
|
106
|
+
const ref = JSON.parse(fs.readFileSync(refPath, 'utf8'));
|
|
107
|
+
previousSha = typeof ref.sha === 'string' ? ref.sha : undefined;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// A missing or malformed sidecar is treated as unknown.
|
|
111
|
+
}
|
|
112
|
+
const cachePath = path.join(cm.getReposDir(), key);
|
|
113
|
+
const refreshed = force ||
|
|
114
|
+
previousSha !== remoteSha ||
|
|
115
|
+
(fs.existsSync(cachePath) && !previousSha);
|
|
116
|
+
if (refreshed)
|
|
117
|
+
cm.clear(key);
|
|
118
|
+
fs.mkdirSync(cm.getMetadataDir(), { recursive: true });
|
|
119
|
+
fs.writeFileSync(refPath, JSON.stringify({ sha: remoteSha, checkedAt: Date.now() }, null, 2));
|
|
120
|
+
const info = {
|
|
121
|
+
repo: url,
|
|
122
|
+
branch,
|
|
123
|
+
remoteSha,
|
|
124
|
+
refreshed,
|
|
125
|
+
offline: false,
|
|
126
|
+
local: false,
|
|
127
|
+
};
|
|
128
|
+
templateRefreshMemo.set(memoKey, info);
|
|
129
|
+
return info;
|
|
130
|
+
}
|
|
131
|
+
function formatAge(lastUpdated) {
|
|
132
|
+
const seconds = Math.max(0, Math.floor((Date.now() - lastUpdated) / 1000));
|
|
133
|
+
if (seconds < 60)
|
|
134
|
+
return `${seconds}s`;
|
|
135
|
+
const minutes = Math.floor(seconds / 60);
|
|
136
|
+
if (minutes < 60)
|
|
137
|
+
return `${minutes}m`;
|
|
138
|
+
const hours = Math.floor(minutes / 60);
|
|
139
|
+
if (hours < 24)
|
|
140
|
+
return `${hours}h`;
|
|
141
|
+
return `${Math.floor(hours / 24)}d`;
|
|
142
|
+
}
|
|
143
|
+
export function describeTemplateSource(info, opts = {}) {
|
|
144
|
+
if (info.local)
|
|
145
|
+
return `using local template ${info.repo}`;
|
|
146
|
+
const repoDisplay = info.repo
|
|
147
|
+
.replace(/^https:\/\/github\.com\//, '')
|
|
148
|
+
.replace(/\.git$/, '');
|
|
149
|
+
const label = `${repoDisplay}@${info.branch ?? 'HEAD'}`;
|
|
150
|
+
const shortSha = info.remoteSha?.slice(0, 7);
|
|
151
|
+
let fetched;
|
|
152
|
+
if (info.refreshed) {
|
|
153
|
+
fetched = 'fetched just now';
|
|
154
|
+
}
|
|
155
|
+
else if (info.remoteSha) {
|
|
156
|
+
const url = new GitCloner().normalizeUrl(info.repo);
|
|
157
|
+
const cm = new CacheManager({
|
|
158
|
+
toolName: opts.toolName ?? DEFAULT_TEMPLATE_TOOL_NAME,
|
|
159
|
+
baseDir: resolveCacheBaseDir(opts.cacheBaseDir),
|
|
160
|
+
});
|
|
161
|
+
const key = cm.createKey(url, info.branch);
|
|
162
|
+
const metadata = cm.getMetadata(key);
|
|
163
|
+
if (metadata?.lastUpdated)
|
|
164
|
+
fetched = `fetched ${formatAge(metadata.lastUpdated)} ago`;
|
|
165
|
+
}
|
|
166
|
+
const details = [
|
|
167
|
+
shortSha,
|
|
168
|
+
fetched,
|
|
169
|
+
].filter(Boolean).join(', ');
|
|
170
|
+
let result = `using ${label}${details ? ` (${details})` : ''}`;
|
|
171
|
+
if (info.offline)
|
|
172
|
+
result += ' (offline, using cached copy)';
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
29
175
|
export function inspectTemplate(options) {
|
|
30
176
|
const { fromPath, templateRepo = DEFAULT_TEMPLATE_REPO, branch, cacheTtlMs = DEFAULT_TEMPLATE_TTL_MS, toolName = DEFAULT_TEMPLATE_TOOL_NAME, cwd, cacheBaseDir, dir, } = options;
|
|
31
177
|
const scaffolder = new TemplateScaffolder({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgpmjs/core",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.30.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "PGPM Package and Migration Tools",
|
|
6
6
|
"main": "index.js",
|
|
@@ -49,27 +49,27 @@
|
|
|
49
49
|
"makage": "^0.8.0"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@pgpmjs/ast": "^0.
|
|
53
|
-
"@pgpmjs/bundle": "^0.
|
|
54
|
-
"@pgpmjs/diff": "^0.
|
|
55
|
-
"@pgpmjs/env": "^2.
|
|
56
|
-
"@pgpmjs/logger": "^2.
|
|
57
|
-
"@pgpmjs/server-utils": "^3.
|
|
58
|
-
"@pgpmjs/slice": "^0.
|
|
59
|
-
"@pgpmjs/transform": "^0.
|
|
60
|
-
"@pgpmjs/types": "^2.
|
|
52
|
+
"@pgpmjs/ast": "^0.15.0",
|
|
53
|
+
"@pgpmjs/bundle": "^0.18.0",
|
|
54
|
+
"@pgpmjs/diff": "^0.7.0",
|
|
55
|
+
"@pgpmjs/env": "^2.45.0",
|
|
56
|
+
"@pgpmjs/logger": "^2.26.0",
|
|
57
|
+
"@pgpmjs/server-utils": "^3.29.0",
|
|
58
|
+
"@pgpmjs/slice": "^0.18.0",
|
|
59
|
+
"@pgpmjs/transform": "^0.27.0",
|
|
60
|
+
"@pgpmjs/types": "^2.55.0",
|
|
61
61
|
"cross-spawn": "^7.0.6",
|
|
62
|
-
"csv-to-pg": "^4.
|
|
62
|
+
"csv-to-pg": "^4.13.0",
|
|
63
63
|
"genomic": "^5.6.6",
|
|
64
64
|
"git-changed": "^0.4.0",
|
|
65
65
|
"glob": "^13.0.6",
|
|
66
66
|
"parse-package-name": "^1.0.0",
|
|
67
67
|
"pg": "^8.21.0",
|
|
68
|
-
"pg-cache": "^3.
|
|
69
|
-
"pg-env": "^1.
|
|
68
|
+
"pg-cache": "^3.29.0",
|
|
69
|
+
"pg-env": "^1.32.0",
|
|
70
70
|
"pgsql-deparser": "^18.3.6",
|
|
71
71
|
"pgsql-parser": "^18.2.6",
|
|
72
72
|
"yanse": "^0.2.2"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "79b4264038d5c4da44ac1ed461195a4853f3953c"
|
|
75
75
|
}
|