@aspan-corporation/ac-shared 1.2.26 → 1.2.27
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/lib/services/dynamoDB.d.ts +4 -1
- package/lib/services/dynamoDB.js +4 -1
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/utils/parseFolderDate.d.ts +29 -0
- package/lib/utils/parseFolderDate.js +25 -0
- package/lib/utils/processMeta.js +17 -29
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
2
|
import { AssumeRoleCommandOutput } from "@aws-sdk/client-sts";
|
|
3
|
-
import { DynamoDBDocumentClient, GetCommandInput, GetCommandOutput, PutCommandInput, PutCommandOutput, QueryCommandInput, QueryCommandOutput, UpdateCommandInput, UpdateCommandOutput, ScanCommandInput, ScanCommandOutput, BatchWriteCommandInput, BatchWriteCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
3
|
+
import { DynamoDBDocumentClient, GetCommandInput, GetCommandOutput, PutCommandInput, PutCommandOutput, QueryCommandInput, QueryCommandOutput, UpdateCommandInput, UpdateCommandOutput, ScanCommandInput, ScanCommandOutput, BatchWriteCommandInput, BatchWriteCommandOutput, BatchGetCommandInput, BatchGetCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
4
4
|
import { Logger } from "@aws-lambda-powertools/logger";
|
|
5
5
|
export declare class DynamoDBService {
|
|
6
6
|
logger: Logger;
|
|
@@ -19,6 +19,7 @@ export declare class DynamoDBService {
|
|
|
19
19
|
checkIfItemExists(checkInput: Pick<GetCommandInput, "TableName" | "Key">): Promise<boolean>;
|
|
20
20
|
scanCommand(scanCommandInput: ScanCommandInput): Promise<ScanCommandOutput>;
|
|
21
21
|
batchWriteCommand(batchWriteCommandInput: BatchWriteCommandInput): Promise<BatchWriteCommandOutput>;
|
|
22
|
+
batchGetCommand(batchGetCommandInput: BatchGetCommandInput): Promise<BatchGetCommandOutput>;
|
|
22
23
|
}
|
|
23
24
|
export type { PutCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
24
25
|
export type { BatchWriteCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
@@ -27,6 +28,8 @@ export type { QueryCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
|
27
28
|
export type { GetCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
28
29
|
export type { UpdateCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
29
30
|
export type { BatchWriteCommandInput } from "@aws-sdk/lib-dynamodb";
|
|
31
|
+
export type { BatchGetCommandInput } from "@aws-sdk/lib-dynamodb";
|
|
32
|
+
export type { BatchGetCommandOutput } from "@aws-sdk/lib-dynamodb";
|
|
30
33
|
export type { PutCommandInput } from "@aws-sdk/lib-dynamodb";
|
|
31
34
|
export type { ScanCommandInput } from "@aws-sdk/lib-dynamodb";
|
|
32
35
|
export type { QueryCommandInput } from "@aws-sdk/lib-dynamodb";
|
package/lib/services/dynamoDB.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
-
import { DynamoDBDocumentClient, GetCommand, PutCommand, QueryCommand, UpdateCommand, ScanCommand, BatchWriteCommand } from "@aws-sdk/lib-dynamodb";
|
|
2
|
+
import { DynamoDBDocumentClient, GetCommand, PutCommand, QueryCommand, UpdateCommand, ScanCommand, BatchWriteCommand, BatchGetCommand } from "@aws-sdk/lib-dynamodb";
|
|
3
3
|
import assert from "node:assert/strict";
|
|
4
4
|
import { getObjectWithAssumeRoleCommandOutputAttribute } from "../utils/index.js";
|
|
5
5
|
export class DynamoDBService {
|
|
@@ -42,4 +42,7 @@ export class DynamoDBService {
|
|
|
42
42
|
async batchWriteCommand(batchWriteCommandInput) {
|
|
43
43
|
return await this.client.send(new BatchWriteCommand(batchWriteCommandInput));
|
|
44
44
|
}
|
|
45
|
+
async batchGetCommand(batchGetCommandInput) {
|
|
46
|
+
return await this.client.send(new BatchGetCommand(batchGetCommandInput));
|
|
47
|
+
}
|
|
45
48
|
}
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a date prefix from a folder name.
|
|
3
|
+
*
|
|
4
|
+
* Recognises:
|
|
5
|
+
* YYYYMMDD[non-digit...] e.g. "20100321. Playground"
|
|
6
|
+
* YYYY-MM-DD[...] e.g. "2024-08-15 Vacation"
|
|
7
|
+
* YYYY.MM.DD[...] e.g. "2024.08.15 Vacation"
|
|
8
|
+
*
|
|
9
|
+
* Folder ids may be passed as the full path ("media/2024/08/15/foo/") or
|
|
10
|
+
* just the bare segment — we always extract the last non-empty segment first.
|
|
11
|
+
*
|
|
12
|
+
* Returns:
|
|
13
|
+
* { year, month1, day, isoDate } where month1 is 1-indexed (1=Jan, 12=Dec).
|
|
14
|
+
* null if the segment doesn't start with a recognisable date.
|
|
15
|
+
*
|
|
16
|
+
* The previous implementation in `processMeta.ts` had a bug rejecting January
|
|
17
|
+
* (it checked `month0 < 1`, where month0 was 0-indexed). It also constructed
|
|
18
|
+
* dates in local time, which differs by region. This implementation:
|
|
19
|
+
* - validates 1 ≤ month ≤ 12 and 1 ≤ day ≤ 31 (so January is included)
|
|
20
|
+
* - emits a UTC ISO timestamp via Date.UTC, eliminating timezone drift
|
|
21
|
+
* - returns 1-indexed month for consumer convenience
|
|
22
|
+
*/
|
|
23
|
+
export type ParsedFolderDate = {
|
|
24
|
+
year: number;
|
|
25
|
+
month1: number;
|
|
26
|
+
day: number;
|
|
27
|
+
isoDate: string;
|
|
28
|
+
};
|
|
29
|
+
export declare const parseFolderDate: (id: string) => ParsedFolderDate | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const COMPACT = /^(\d{4})(\d{2})(\d{2})/;
|
|
2
|
+
const SEPARATED = /^(\d{4})[-.](\d{2})[-.](\d{2})/;
|
|
3
|
+
export const parseFolderDate = (id) => {
|
|
4
|
+
// Last non-empty path segment
|
|
5
|
+
const segment = id.replace(/\/$/, "").split("/").pop() ?? "";
|
|
6
|
+
if (!segment)
|
|
7
|
+
return null;
|
|
8
|
+
const match = COMPACT.exec(segment) ?? SEPARATED.exec(segment);
|
|
9
|
+
if (!match)
|
|
10
|
+
return null;
|
|
11
|
+
const year = Number(match[1]);
|
|
12
|
+
const month1 = Number(match[2]);
|
|
13
|
+
const day = Number(match[3]);
|
|
14
|
+
if (Number.isNaN(year) || Number.isNaN(month1) || Number.isNaN(day))
|
|
15
|
+
return null;
|
|
16
|
+
if (year < 1900 || year > 2100)
|
|
17
|
+
return null;
|
|
18
|
+
if (month1 < 1 || month1 > 12)
|
|
19
|
+
return null;
|
|
20
|
+
if (day < 1 || day > 31)
|
|
21
|
+
return null;
|
|
22
|
+
// UTC midnight to avoid timezone drift in toISOString().
|
|
23
|
+
const isoDate = new Date(Date.UTC(year, month1 - 1, day)).toISOString();
|
|
24
|
+
return { year, month1, day, isoDate };
|
|
25
|
+
};
|
package/lib/utils/processMeta.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
1
|
import { getKeyExtension } from "./thumbsKey.js";
|
|
2
|
+
import { parseFolderDate } from "./parseFolderDate.js";
|
|
3
3
|
/**
|
|
4
4
|
* 1. read <id>
|
|
5
5
|
* 2. if <id> doesn't exist then use PutCommand
|
|
@@ -125,38 +125,26 @@ export const deriveFolder = (id) => {
|
|
|
125
125
|
return "/";
|
|
126
126
|
return trimmed.slice(0, lastSlash + 1);
|
|
127
127
|
};
|
|
128
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Derive date tags from the parent folder's name when it begins with a
|
|
130
|
+
* recognised date prefix (YYYYMMDD, YYYY-MM-DD, YYYY.MM.DD).
|
|
131
|
+
*
|
|
132
|
+
* Operates on the parent folder of the given key — for "media/20240815/photo.jpg"
|
|
133
|
+
* it parses "20240815". The previous implementation skipped January due to
|
|
134
|
+
* a 0-vs-1-indexed month bug; that has been fixed in `parseFolderDate`.
|
|
135
|
+
*/
|
|
129
136
|
const extractMetaFromKey = (key) => {
|
|
130
137
|
if (!key)
|
|
131
138
|
return [];
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
firstToken = folder.split(".")[0];
|
|
137
|
-
}
|
|
138
|
-
catch (error) { }
|
|
139
|
-
if (firstToken === undefined ||
|
|
140
|
-
firstToken.length !== 8 ||
|
|
141
|
-
!firstToken.startsWith(SUBSTRING_ANSI_DATES_BEGIN_WITH))
|
|
139
|
+
// Look at the parent folder, not the file itself.
|
|
140
|
+
const parent = key.endsWith("/") ? key : key.slice(0, key.lastIndexOf("/") + 1);
|
|
141
|
+
const parsed = parseFolderDate(parent);
|
|
142
|
+
if (!parsed)
|
|
142
143
|
return [];
|
|
143
|
-
const year = Number(firstToken.substring(0, 4));
|
|
144
|
-
const month = Number(firstToken.substring(4, 6)) - 1;
|
|
145
|
-
const day = Number(firstToken.substring(6));
|
|
146
|
-
if (isNaN(year) || isNaN(month) || isNaN(day))
|
|
147
|
-
return [];
|
|
148
|
-
// mon starts from 0
|
|
149
|
-
// day starts from 1
|
|
150
|
-
if (year < 2000 || month < 1 || month > 11 || day < 1 || day > 31)
|
|
151
|
-
return [];
|
|
152
|
-
const dateCreatedBin = new Date(year, month, day);
|
|
153
144
|
return [
|
|
154
|
-
{ key: "dateCreated", value:
|
|
155
|
-
{ key: "yearCreated", value:
|
|
156
|
-
{ key: "dayCreated", value:
|
|
157
|
-
{
|
|
158
|
-
key: "monthCreated",
|
|
159
|
-
value: (dateCreatedBin.getMonth() + 1).toString()
|
|
160
|
-
}
|
|
145
|
+
{ key: "dateCreated", value: parsed.isoDate },
|
|
146
|
+
{ key: "yearCreated", value: String(parsed.year) },
|
|
147
|
+
{ key: "dayCreated", value: String(parsed.day) },
|
|
148
|
+
{ key: "monthCreated", value: String(parsed.month1) },
|
|
161
149
|
];
|
|
162
150
|
};
|