paperclip-github-plugin 0.9.1 → 0.9.3
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 +5 -0
- package/dist/manifest.js +1 -1
- package/dist/ui/index.js +59 -6
- package/dist/ui/index.js.map +2 -2
- package/dist/worker.js +114 -0
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -1992,6 +1992,20 @@ function normalizeGitHubTokensByCompanyId(value) {
|
|
|
1992
1992
|
}
|
|
1993
1993
|
return Object.fromEntries(entries);
|
|
1994
1994
|
}
|
|
1995
|
+
function normalizePaperclipBoardApiTokensByCompanyId(value) {
|
|
1996
|
+
if (!value || typeof value !== "object") {
|
|
1997
|
+
return void 0;
|
|
1998
|
+
}
|
|
1999
|
+
const entries = Object.entries(value).map(([companyId, token]) => {
|
|
2000
|
+
const normalizedCompanyId = normalizeCompanyId(companyId);
|
|
2001
|
+
const normalizedToken = normalizeGitHubToken(token);
|
|
2002
|
+
return normalizedCompanyId && normalizedToken ? [normalizedCompanyId, normalizedToken] : null;
|
|
2003
|
+
}).filter((entry) => entry !== null);
|
|
2004
|
+
if (entries.length === 0) {
|
|
2005
|
+
return void 0;
|
|
2006
|
+
}
|
|
2007
|
+
return Object.fromEntries(entries);
|
|
2008
|
+
}
|
|
1995
2009
|
function formatUtcTimestamp(value) {
|
|
1996
2010
|
const parsed = new Date(value);
|
|
1997
2011
|
if (Number.isNaN(parsed.getTime())) {
|
|
@@ -3730,6 +3744,7 @@ function normalizeConfig(value) {
|
|
|
3730
3744
|
const githubToken = normalizeGitHubToken(record.githubToken);
|
|
3731
3745
|
const githubTokensByCompanyId = normalizeGitHubTokensByCompanyId(record.githubTokensByCompanyId);
|
|
3732
3746
|
const paperclipBoardApiTokenRefs = normalizePaperclipBoardApiTokenRefs(record.paperclipBoardApiTokenRefs);
|
|
3747
|
+
const paperclipBoardApiTokensByCompanyId = normalizePaperclipBoardApiTokensByCompanyId(record.paperclipBoardApiTokensByCompanyId);
|
|
3733
3748
|
const paperclipApiBaseUrl = normalizePaperclipApiBaseUrl(record.paperclipApiBaseUrl);
|
|
3734
3749
|
return {
|
|
3735
3750
|
...githubTokenRefs ? { githubTokenRefs } : {},
|
|
@@ -3737,6 +3752,7 @@ function normalizeConfig(value) {
|
|
|
3737
3752
|
...githubToken ? { githubToken } : {},
|
|
3738
3753
|
...githubTokensByCompanyId ? { githubTokensByCompanyId } : {},
|
|
3739
3754
|
...paperclipBoardApiTokenRefs ? { paperclipBoardApiTokenRefs } : {},
|
|
3755
|
+
...paperclipBoardApiTokensByCompanyId ? { paperclipBoardApiTokensByCompanyId } : {},
|
|
3740
3756
|
...paperclipApiBaseUrl ? { paperclipApiBaseUrl } : {}
|
|
3741
3757
|
};
|
|
3742
3758
|
}
|
|
@@ -3860,6 +3876,80 @@ async function writeExternalCompanyGitHubTokenFallback(ctx, companyId, token) {
|
|
|
3860
3876
|
});
|
|
3861
3877
|
}
|
|
3862
3878
|
}
|
|
3879
|
+
async function writeExternalCompanyPaperclipBoardApiTokenFallback(ctx, companyId, token) {
|
|
3880
|
+
const externalConfigFilePath = getExternalConfigFilePath();
|
|
3881
|
+
if (!externalConfigFilePath) {
|
|
3882
|
+
throw new Error("Could not resolve a Paperclip home directory for the GitHub Sync fallback token config.");
|
|
3883
|
+
}
|
|
3884
|
+
const currentRecord = await readExternalConfigRecordForWrite(ctx, externalConfigFilePath);
|
|
3885
|
+
const currentCompanyTokens = normalizePaperclipBoardApiTokensByCompanyId(currentRecord.paperclipBoardApiTokensByCompanyId) ?? {};
|
|
3886
|
+
const nextRecord = {
|
|
3887
|
+
...currentRecord,
|
|
3888
|
+
paperclipBoardApiTokensByCompanyId: {
|
|
3889
|
+
...currentCompanyTokens,
|
|
3890
|
+
[companyId]: token
|
|
3891
|
+
}
|
|
3892
|
+
};
|
|
3893
|
+
await mkdir(dirname(externalConfigFilePath), { recursive: true });
|
|
3894
|
+
await writeFile(externalConfigFilePath, `${JSON.stringify(nextRecord, null, 2)}
|
|
3895
|
+
`, {
|
|
3896
|
+
encoding: "utf8",
|
|
3897
|
+
mode: 384
|
|
3898
|
+
});
|
|
3899
|
+
try {
|
|
3900
|
+
await chmod(externalConfigFilePath, 384);
|
|
3901
|
+
} catch (error) {
|
|
3902
|
+
ctx.logger.warn("GitHub Sync could not tighten permissions on the worker-local token fallback file.", {
|
|
3903
|
+
filePath: externalConfigFilePath,
|
|
3904
|
+
error: getErrorMessage(error)
|
|
3905
|
+
});
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
async function clearExternalCompanyPaperclipBoardApiTokenFallback(ctx, companyId) {
|
|
3909
|
+
const externalConfigFilePath = getExternalConfigFilePath();
|
|
3910
|
+
if (!externalConfigFilePath) {
|
|
3911
|
+
return;
|
|
3912
|
+
}
|
|
3913
|
+
const currentRecord = await readExternalConfigRecordForWrite(ctx, externalConfigFilePath);
|
|
3914
|
+
const currentCompanyTokens = normalizePaperclipBoardApiTokensByCompanyId(currentRecord.paperclipBoardApiTokensByCompanyId) ?? {};
|
|
3915
|
+
if (!(companyId in currentCompanyTokens)) {
|
|
3916
|
+
return;
|
|
3917
|
+
}
|
|
3918
|
+
const nextCompanyTokens = { ...currentCompanyTokens };
|
|
3919
|
+
delete nextCompanyTokens[companyId];
|
|
3920
|
+
const nextRecord = { ...currentRecord };
|
|
3921
|
+
if (Object.keys(nextCompanyTokens).length > 0) {
|
|
3922
|
+
nextRecord.paperclipBoardApiTokensByCompanyId = nextCompanyTokens;
|
|
3923
|
+
} else {
|
|
3924
|
+
delete nextRecord.paperclipBoardApiTokensByCompanyId;
|
|
3925
|
+
}
|
|
3926
|
+
await mkdir(dirname(externalConfigFilePath), { recursive: true });
|
|
3927
|
+
await writeFile(externalConfigFilePath, `${JSON.stringify(nextRecord, null, 2)}
|
|
3928
|
+
`, {
|
|
3929
|
+
encoding: "utf8",
|
|
3930
|
+
mode: 384
|
|
3931
|
+
});
|
|
3932
|
+
try {
|
|
3933
|
+
await chmod(externalConfigFilePath, 384);
|
|
3934
|
+
} catch (error) {
|
|
3935
|
+
ctx.logger.warn("GitHub Sync could not tighten permissions on the worker-local token fallback file.", {
|
|
3936
|
+
filePath: externalConfigFilePath,
|
|
3937
|
+
error: getErrorMessage(error)
|
|
3938
|
+
});
|
|
3939
|
+
}
|
|
3940
|
+
}
|
|
3941
|
+
async function shouldSeedExternalPaperclipBoardTokenFallback(ctx, companyId, secretRef) {
|
|
3942
|
+
try {
|
|
3943
|
+
return !(await ctx.secrets.resolve(secretRef)).trim();
|
|
3944
|
+
} catch (error) {
|
|
3945
|
+
ctx.logger.warn("Unable to resolve the saved Paperclip board API token while checking worker fallback necessity.", {
|
|
3946
|
+
companyId,
|
|
3947
|
+
secretRef,
|
|
3948
|
+
error: getErrorMessage(error)
|
|
3949
|
+
});
|
|
3950
|
+
return true;
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3863
3953
|
function normalizePaperclipBoardApiTokenRefs(value) {
|
|
3864
3954
|
if (!value || typeof value !== "object") {
|
|
3865
3955
|
return void 0;
|
|
@@ -10146,11 +10236,16 @@ async function resolvePaperclipApiAuthTokens(ctx, settings, config, mappings) {
|
|
|
10146
10236
|
for (const companyId of companyIds) {
|
|
10147
10237
|
const configuredSecretRef = getConfiguredPaperclipBoardApiTokenRef(config, companyId);
|
|
10148
10238
|
const savedSecretRef = getSavedPaperclipBoardApiTokenRef(settings, companyId);
|
|
10239
|
+
const fallbackToken = normalizeGitHubToken(config.paperclipBoardApiTokensByCompanyId?.[companyId]);
|
|
10149
10240
|
const secretRef = configuredSecretRef ?? savedSecretRef;
|
|
10150
10241
|
if (!secretRef) {
|
|
10151
10242
|
continue;
|
|
10152
10243
|
}
|
|
10153
10244
|
if (!configuredSecretRef && savedSecretRef) {
|
|
10245
|
+
if (fallbackToken) {
|
|
10246
|
+
tokensByCompanyId.set(companyId, fallbackToken);
|
|
10247
|
+
continue;
|
|
10248
|
+
}
|
|
10154
10249
|
ctx.logger.warn(
|
|
10155
10250
|
"Paperclip board access is saved in plugin state but has not been mirrored into plugin config yet. Open plugin settings to finish migrating it, or reconnect board access, before retrying sync.",
|
|
10156
10251
|
{
|
|
@@ -10166,6 +10261,15 @@ async function resolvePaperclipApiAuthTokens(ctx, settings, config, mappings) {
|
|
|
10166
10261
|
tokensByCompanyId.set(companyId, token);
|
|
10167
10262
|
}
|
|
10168
10263
|
} catch (error) {
|
|
10264
|
+
if (fallbackToken && isPluginSecretReferenceDisabledError(error)) {
|
|
10265
|
+
ctx.logger.warn("GitHub Sync is using a worker-local Paperclip board token fallback because plugin secret refs are unavailable in this host.", {
|
|
10266
|
+
companyId,
|
|
10267
|
+
secretRef,
|
|
10268
|
+
error: getErrorMessage(error)
|
|
10269
|
+
});
|
|
10270
|
+
tokensByCompanyId.set(companyId, fallbackToken);
|
|
10271
|
+
continue;
|
|
10272
|
+
}
|
|
10169
10273
|
ctx.logger.warn("Unable to resolve the saved Paperclip board API token. Direct REST calls will continue without it.", {
|
|
10170
10274
|
companyId,
|
|
10171
10275
|
secretRef,
|
|
@@ -15654,6 +15758,7 @@ var __testing = {
|
|
|
15654
15758
|
formatPaperclipApiFetchErrorMessage,
|
|
15655
15759
|
hasUnresolvedPaperclipIssueBlocker,
|
|
15656
15760
|
isHealthyMaintainerWaitTransition,
|
|
15761
|
+
resolvePaperclipApiAuthTokens,
|
|
15657
15762
|
resolveGithubToken,
|
|
15658
15763
|
resolvePaperclipPullRequestIssueStatus,
|
|
15659
15764
|
resolveSyncTransitionAssignee
|
|
@@ -15898,6 +16003,7 @@ var plugin = definePlugin({
|
|
|
15898
16003
|
throw new Error("A company id is required to update Paperclip board access.");
|
|
15899
16004
|
}
|
|
15900
16005
|
const nextSecretRef = normalizeSecretRef(record.paperclipBoardApiTokenRef);
|
|
16006
|
+
const nextBoardApiToken = normalizeGitHubToken(record.paperclipBoardApiToken);
|
|
15901
16007
|
const nextPaperclipBoardApiTokenRefs = {
|
|
15902
16008
|
...previous.paperclipBoardApiTokenRefs ?? {}
|
|
15903
16009
|
};
|
|
@@ -15909,10 +16015,18 @@ var plugin = definePlugin({
|
|
|
15909
16015
|
};
|
|
15910
16016
|
if (nextSecretRef) {
|
|
15911
16017
|
nextPaperclipBoardApiTokenRefs[companyId] = nextSecretRef;
|
|
16018
|
+
if (nextBoardApiToken) {
|
|
16019
|
+
if (await shouldSeedExternalPaperclipBoardTokenFallback(ctx, companyId, nextSecretRef)) {
|
|
16020
|
+
await writeExternalCompanyPaperclipBoardApiTokenFallback(ctx, companyId, nextBoardApiToken);
|
|
16021
|
+
} else {
|
|
16022
|
+
await clearExternalCompanyPaperclipBoardApiTokenFallback(ctx, companyId);
|
|
16023
|
+
}
|
|
16024
|
+
}
|
|
15912
16025
|
} else {
|
|
15913
16026
|
delete nextPaperclipBoardApiTokenRefs[companyId];
|
|
15914
16027
|
delete nextPaperclipBoardAccessIdentityByCompanyId[companyId];
|
|
15915
16028
|
delete nextPaperclipBoardAccessUserIdByCompanyId[companyId];
|
|
16029
|
+
await clearExternalCompanyPaperclipBoardApiTokenFallback(ctx, companyId);
|
|
15916
16030
|
}
|
|
15917
16031
|
if ("paperclipBoardAccessIdentity" in record) {
|
|
15918
16032
|
const nextIdentityLabel = normalizeOptionalString2(record.paperclipBoardAccessIdentity);
|