@toolproof-npm/shared 0.1.14

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 ADDED
@@ -0,0 +1,55 @@
1
+ # @toolproof-npm/shared
2
+
3
+ Core library utilities for ToolProof.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @toolproof-npm/shared
9
+ # or
10
+ npm install @toolproof-npm/shared
11
+ # or
12
+ yarn add @toolproof-npm/shared
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Basic Import
18
+
19
+ ```typescript
20
+ import { /* your exports */ } from '@toolproof-npm/shared';
21
+ ```
22
+
23
+ ### Constants
24
+
25
+ ```typescript
26
+ import { /* constants */ } from '@toolproof-npm/shared/constants';
27
+ ```
28
+
29
+ ### Types
30
+
31
+ ```typescript
32
+ import { /* types */ } from '@toolproof-npm/shared/types';
33
+ ```
34
+
35
+ ### Server Utilities (Node.js only)
36
+
37
+ ```typescript
38
+ import { /* server utilities */ } from '@toolproof-npm/shared/server';
39
+ ```
40
+
41
+ ## Features
42
+
43
+ - TypeScript support with full type definitions
44
+ - ESM module format
45
+ - Tree-shakeable exports
46
+ - Server-side utilities for Firestore admin operations
47
+
48
+ ## Requirements
49
+
50
+ - Node.js 16+
51
+ - TypeScript 4.5+ (for TypeScript projects)
52
+
53
+ ## License
54
+
55
+ MIT
@@ -0,0 +1,65 @@
1
+ export declare const CONSTANTS: {
2
+ readonly SCHEMA: {
3
+ readonly FormatData: "FormatData";
4
+ readonly TypeData: "TypeData";
5
+ readonly SignatureData: "SignatureData";
6
+ readonly JobData: "JobData";
7
+ readonly Execution: "Execution";
8
+ readonly ResourceMap: "ResourceMap";
9
+ };
10
+ readonly STORAGE: {
11
+ readonly BUCKETS: {
12
+ readonly tp_shapes: "tp-shapes";
13
+ readonly tp_resources: "tp-resources";
14
+ };
15
+ readonly COLLECTIONS: {
16
+ readonly shapes: "shapes";
17
+ readonly resources: "resources";
18
+ };
19
+ readonly FILTER: {
20
+ readonly members: "members";
21
+ readonly specials: "specials";
22
+ };
23
+ };
24
+ readonly SHAPES: {
25
+ readonly formats: "formats";
26
+ readonly types: "types";
27
+ };
28
+ readonly SHAPES_PSEUDO: {
29
+ readonly roles: "roles";
30
+ };
31
+ readonly RESOURCES: {
32
+ readonly resources: "resources";
33
+ readonly jobs: "jobs";
34
+ };
35
+ readonly STEP: {
36
+ readonly work: "work";
37
+ readonly branch: "branch";
38
+ readonly while: "while";
39
+ readonly for: "for";
40
+ };
41
+ readonly WORKFLOW: {
42
+ readonly execution: "execution";
43
+ readonly workflow: "workflow";
44
+ readonly workflowSpec: "workflowSpec";
45
+ };
46
+ readonly ENGINE: {
47
+ readonly GraphRunWorkflow: "GraphRunWorkflow";
48
+ };
49
+ readonly SPECIALS: {
50
+ readonly FORMAT_ApplicationPrimitive: "FORMAT-ApplicationPrimitive";
51
+ readonly FORMAT_ApplicationJson: "FORMAT-ApplicationJson";
52
+ readonly FORMAT_ApplicationJob: "FORMAT-ApplicationJob";
53
+ readonly TYPE_Boolean: "TYPE-Boolean";
54
+ readonly TYPE_Integer: "TYPE-Integer";
55
+ readonly TYPE_Job: "TYPE-Job";
56
+ readonly TYPE_WorkflowSpec: "TYPE-WorkflowSpec";
57
+ readonly ROLE_BUILDER: "ROLE-Builder";
58
+ readonly JOB_Engine: "JOB-Engine";
59
+ readonly BOOLEAN_false: "RESOURCE-CSTseYlo7VxcNFl9RMvD";
60
+ readonly BOOLEAN_true: "RESOURCE-V4TFSye2F7bBnEsSrpH4";
61
+ };
62
+ readonly TESTING: {
63
+ readonly Integer_Zero: "TYPE-Integer/3335e31095a13a9a2b0ea41ca7d92a458780cd5671dc0a440a72cc1b1c4f2c81";
64
+ };
65
+ };
@@ -0,0 +1,65 @@
1
+ export const CONSTANTS = {
2
+ SCHEMA: {
3
+ FormatData: 'FormatData',
4
+ TypeData: 'TypeData',
5
+ SignatureData: 'SignatureData',
6
+ JobData: 'JobData',
7
+ Execution: 'Execution',
8
+ ResourceMap: 'ResourceMap',
9
+ },
10
+ STORAGE: {
11
+ BUCKETS: {
12
+ tp_shapes: 'tp-shapes',
13
+ tp_resources: 'tp-resources',
14
+ },
15
+ COLLECTIONS: {
16
+ shapes: 'shapes',
17
+ resources: 'resources',
18
+ },
19
+ FILTER: {
20
+ members: 'members',
21
+ specials: 'specials',
22
+ }
23
+ },
24
+ SHAPES: {
25
+ formats: 'formats',
26
+ types: 'types',
27
+ },
28
+ SHAPES_PSEUDO: {
29
+ roles: 'roles',
30
+ },
31
+ RESOURCES: {
32
+ resources: 'resources',
33
+ jobs: 'jobs',
34
+ },
35
+ STEP: {
36
+ work: 'work',
37
+ branch: 'branch',
38
+ while: 'while',
39
+ for: 'for',
40
+ },
41
+ WORKFLOW: {
42
+ execution: 'execution',
43
+ workflow: 'workflow',
44
+ workflowSpec: 'workflowSpec',
45
+ },
46
+ ENGINE: {
47
+ GraphRunWorkflow: 'GraphRunWorkflow',
48
+ },
49
+ SPECIALS: {
50
+ FORMAT_ApplicationPrimitive: 'FORMAT-ApplicationPrimitive',
51
+ FORMAT_ApplicationJson: 'FORMAT-ApplicationJson',
52
+ FORMAT_ApplicationJob: 'FORMAT-ApplicationJob',
53
+ TYPE_Boolean: 'TYPE-Boolean',
54
+ TYPE_Integer: 'TYPE-Integer',
55
+ TYPE_Job: 'TYPE-Job',
56
+ TYPE_WorkflowSpec: 'TYPE-WorkflowSpec',
57
+ ROLE_BUILDER: 'ROLE-Builder',
58
+ JOB_Engine: 'JOB-Engine',
59
+ BOOLEAN_false: 'RESOURCE-CSTseYlo7VxcNFl9RMvD',
60
+ BOOLEAN_true: 'RESOURCE-V4TFSye2F7bBnEsSrpH4',
61
+ },
62
+ TESTING: {
63
+ Integer_Zero: 'TYPE-Integer/3335e31095a13a9a2b0ea41ca7d92a458780cd5671dc0a440a72cc1b1c4f2c81',
64
+ }
65
+ };
@@ -0,0 +1,7 @@
1
+ import type { TypeIdJson } from '@toolproof-npm/schema';
2
+ import type { FilterConst, ShapeConst, RoleConst, StepConst, WorkflowConst, ShapeMeta, ShapeData, ShapeMetaMap, ShapeDataMap, ResourceMetaMap, ResourceDataMap, ResourceConst } from './types.d.ts';
3
+ export declare function getNewId(identifiable: ShapeConst | RoleConst | ResourceConst | StepConst | WorkflowConst): string;
4
+ export declare function listShapesMeta<T extends ShapeMeta>(groupKey: ShapeConst, filterConfig: Record<FilterConst, boolean>): Promise<ShapeMetaMap<T>>;
5
+ export declare function listResourcesMeta(typeIds: TypeIdJson[]): Promise<ResourceMetaMap>;
6
+ export declare function listShapesData<T extends ShapeData>(groupKey: ShapeConst, filterConfig: Record<FilterConst, boolean>): Promise<ShapeDataMap<T>>;
7
+ export declare function listResourcesData(typeIds: TypeIdJson[]): Promise<ResourceDataMap>;
@@ -0,0 +1,192 @@
1
+ import { CONSTANTS } from './constants.js';
2
+ import { dbAdmin, storageAdmin } from "./firestoreAdminInit.js";
3
+ export function getNewId(identifiable) {
4
+ const base = identifiable.toUpperCase();
5
+ const normalized = base.endsWith('S') ? base.slice(0, -1) : base;
6
+ const prefix = normalized + '-';
7
+ const docRef = dbAdmin.collection(CONSTANTS.STORAGE.COLLECTIONS.shapes).doc(identifiable).collection(CONSTANTS.STORAGE.FILTER.members).doc();
8
+ return prefix + docRef.id;
9
+ }
10
+ export async function listShapesMeta(groupKey, filterConfig) {
11
+ const baseRef = dbAdmin
12
+ .collection(CONSTANTS.STORAGE.COLLECTIONS.shapes)
13
+ .doc(groupKey);
14
+ const entries = await Promise.all([
15
+ filterConfig.members
16
+ ? baseRef.collection(CONSTANTS.STORAGE.FILTER.members).get().then(snap => snap.docs.map(d => {
17
+ const data = d.data();
18
+ return { ...data, id: d.id };
19
+ }))
20
+ : Promise.resolve([]),
21
+ filterConfig.specials
22
+ ? baseRef.collection(CONSTANTS.STORAGE.FILTER.specials).get().then(snap => snap.docs.map(d => {
23
+ const data = d.data();
24
+ return { ...data, id: d.id };
25
+ }))
26
+ : Promise.resolve([]),
27
+ ]);
28
+ const [members, specials] = entries;
29
+ return { members, specials };
30
+ }
31
+ export async function listResourcesMeta(typeIds) {
32
+ const collectionName = CONSTANTS.STORAGE.COLLECTIONS.resources;
33
+ const entries = await Promise.all(typeIds.map(async (typeId) => {
34
+ const snap = await dbAdmin
35
+ .collection(collectionName)
36
+ .doc(typeId)
37
+ .collection(CONSTANTS.STORAGE.FILTER.members)
38
+ .get();
39
+ const items = snap.docs.map(d => {
40
+ const data = d.data();
41
+ // Ensure id field is present (doc id is the resourceId)
42
+ return { ...data, id: d.id };
43
+ });
44
+ return [typeId, items];
45
+ }));
46
+ return Object.fromEntries(entries);
47
+ }
48
+ export async function listShapesData(groupKey, filterConfig) {
49
+ const bucket = storageAdmin.bucket(CONSTANTS.STORAGE.BUCKETS.tp_shapes);
50
+ const prefix = `${groupKey}/`;
51
+ const [files] = await bucket.getFiles({ prefix });
52
+ const result = {
53
+ members: [],
54
+ specials: [],
55
+ };
56
+ const tasks = files
57
+ .filter(f => !(f.name.endsWith('/') || f.name.split('/').pop() === ''))
58
+ .map(async (file) => {
59
+ const meta = file.metadata || (await file.getMetadata())[0];
60
+ const subNameRaw = meta?.metadata?.filter;
61
+ const subName = (subNameRaw === CONSTANTS.STORAGE.FILTER.specials
62
+ ? CONSTANTS.STORAGE.FILTER.specials
63
+ : CONSTANTS.STORAGE.FILTER.members);
64
+ if (!filterConfig[subName])
65
+ return;
66
+ const [buf] = await file.download();
67
+ const json = JSON.parse(buf.toString('utf8'));
68
+ result[subName].push(json);
69
+ });
70
+ await Promise.all(tasks);
71
+ return result;
72
+ }
73
+ export async function listResourcesData(typeIds) {
74
+ const bucket = storageAdmin.bucket(CONSTANTS.STORAGE.BUCKETS.tp_resources);
75
+ async function fetchFilesUnder(typeId) {
76
+ const prefix = `${typeId}/`;
77
+ const [found] = await bucket.getFiles({ prefix });
78
+ const files = found.filter(f => {
79
+ const name = f.name || '';
80
+ if (!name || name.endsWith('/'))
81
+ return false;
82
+ return true;
83
+ });
84
+ if (!files.length)
85
+ return [];
86
+ const items = await Promise.all(files.map(async (file) => {
87
+ try {
88
+ const [buf] = await file.download();
89
+ const meta = file.metadata || (await file.getMetadata())[0];
90
+ const data = JSON.parse(buf.toString('utf8'));
91
+ return { data, meta, name: file.name };
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }));
97
+ return items.filter(Boolean);
98
+ }
99
+ const entries = await Promise.all(typeIds.map(async (typeId) => {
100
+ const rows = await fetchFilesUnder(typeId);
101
+ const items = rows.map(({ data, meta, name }) => {
102
+ const flat = meta?.metadata ?? {};
103
+ // Reconstruct nested object from flattened keys (dot and array index notation)
104
+ const root = {};
105
+ for (const [k, vRaw] of Object.entries(flat)) {
106
+ if (typeof vRaw !== 'string')
107
+ continue; // GCS should store only strings
108
+ const vStr = vRaw.trim();
109
+ // Attempt JSON parse for non-simple primitives
110
+ let value = vStr;
111
+ if ((vStr.startsWith('{') && vStr.endsWith('}')) || (vStr.startsWith('[') && vStr.endsWith(']'))) {
112
+ try {
113
+ value = JSON.parse(vStr);
114
+ }
115
+ catch {
116
+ value = vStr;
117
+ }
118
+ }
119
+ // Split by '.' while preserving array indices
120
+ const segments = k.split('.');
121
+ let cursor = root;
122
+ for (let i = 0; i < segments.length; i++) {
123
+ const seg = segments[i];
124
+ const arrIdxMatch = seg.match(/^(.*)\[(\d+)\]$/);
125
+ if (arrIdxMatch) {
126
+ const base = arrIdxMatch[1];
127
+ const idx = parseInt(arrIdxMatch[2], 10);
128
+ if (!cursor[base])
129
+ cursor[base] = [];
130
+ if (!Array.isArray(cursor[base]))
131
+ cursor[base] = [];
132
+ while (cursor[base].length <= idx)
133
+ cursor[base].push(undefined);
134
+ if (i === segments.length - 1) {
135
+ cursor[base][idx] = value;
136
+ }
137
+ else {
138
+ if (!cursor[base][idx])
139
+ cursor[base][idx] = {};
140
+ cursor = cursor[base][idx];
141
+ }
142
+ }
143
+ else {
144
+ if (i === segments.length - 1) {
145
+ cursor[seg] = value;
146
+ }
147
+ else {
148
+ if (!cursor[seg] || typeof cursor[seg] !== 'object')
149
+ cursor[seg] = {};
150
+ cursor = cursor[seg];
151
+ }
152
+ }
153
+ }
154
+ }
155
+ const idMeta = root.id;
156
+ const typeIdMeta = root.typeId;
157
+ // creationContext may be flattened as creationContext.roleId or direct roleId
158
+ const roleId = (root.creationContext?.roleId ?? root.roleId);
159
+ const executionId = (root.creationContext?.executionId ?? root.executionId);
160
+ const kind = root.kind;
161
+ const path = root.path;
162
+ const timestamp = root.timestamp;
163
+ const missing = [
164
+ ['id', idMeta],
165
+ ['typeId', typeIdMeta],
166
+ ['roleId', roleId],
167
+ ['executionId', executionId],
168
+ ['kind', kind],
169
+ ['path', path],
170
+ ['timestamp', timestamp],
171
+ ].filter(([_, v]) => typeof v !== 'string' || v.length === 0);
172
+ if (missing.length) {
173
+ const keys = missing.map(([k]) => k).join(', ');
174
+ throw new Error(`Missing required metadata keys [${keys}] for resource file: ${name}`);
175
+ }
176
+ return {
177
+ id: idMeta,
178
+ typeId: typeIdMeta,
179
+ creationContext: {
180
+ roleId: roleId,
181
+ executionId: executionId,
182
+ },
183
+ kind: kind,
184
+ path: path,
185
+ timestamp: timestamp,
186
+ extractedData: data,
187
+ };
188
+ });
189
+ return [typeId, items];
190
+ }));
191
+ return Object.fromEntries(entries);
192
+ }
@@ -0,0 +1,3 @@
1
+ declare const dbAdmin: FirebaseFirestore.Firestore;
2
+ declare const storageAdmin: import("firebase-admin/storage").Storage;
3
+ export { dbAdmin, storageAdmin };
@@ -0,0 +1,36 @@
1
+ import { getApp, getApps, initializeApp, applicationDefault, cert } from 'firebase-admin/app';
2
+ import { getFirestore } from 'firebase-admin/firestore';
3
+ import { getStorage } from 'firebase-admin/storage';
4
+ import { existsSync, readFileSync } from 'fs';
5
+ import path from 'path';
6
+ // Resolve credentials: prefer GOOGLE_APPLICATION_CREDENTIALS, fallback to local gcp-key.json, else ADC
7
+ function resolveCredential() {
8
+ const jsonString = process.env.GOOGLE_APPLICATION_CREDENTIALS_JSON;
9
+ const envPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
10
+ const localKeyPath = path.join(process.cwd(), 'gcp-key.json');
11
+ try {
12
+ if (jsonString) {
13
+ const json = JSON.parse(jsonString);
14
+ return cert(json);
15
+ }
16
+ if (envPath && existsSync(envPath)) {
17
+ const json = JSON.parse(readFileSync(envPath, 'utf8'));
18
+ return cert(json);
19
+ }
20
+ if (existsSync(localKeyPath)) {
21
+ const json = JSON.parse(readFileSync(localKeyPath, 'utf8'));
22
+ return cert(json);
23
+ }
24
+ }
25
+ catch {
26
+ // fall through to ADC
27
+ }
28
+ return applicationDefault();
29
+ }
30
+ const app = getApps().length ? getApp() : initializeApp({
31
+ credential: resolveCredential(),
32
+ projectId: "toolproof-563fe",
33
+ });
34
+ const dbAdmin = getFirestore(app);
35
+ const storageAdmin = getStorage(app);
36
+ export { dbAdmin, storageAdmin };
@@ -0,0 +1,3 @@
1
+ export * as CONSTANTS from './constants.js';
2
+ export * as TYPES from './types.js';
3
+ export * from './firestoreAdminHelpers.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * as CONSTANTS from './constants.js';
2
+ export * as TYPES from './types.js';
3
+ export * from './firestoreAdminHelpers.js';
@@ -0,0 +1,32 @@
1
+ import type { ResourceIdJson, ExecutionIdJson, RoleIdJson, RoleLiteralJson, TypeIdJson, FormatMetaJson, FormatDataJson, TypeMetaJson, TypeDataJson, ResourceMetaJson, ResourceDataJson } from '@toolproof-npm/schema';
2
+ import { CONSTANTS } from './constants.js';
3
+ export type BucketConst = typeof CONSTANTS.STORAGE.BUCKETS.tp_shapes | typeof CONSTANTS.STORAGE.BUCKETS.tp_resources;
4
+ export type CollectionConst = typeof CONSTANTS.STORAGE.COLLECTIONS.shapes | typeof CONSTANTS.STORAGE.COLLECTIONS.resources;
5
+ export type FilterConst = typeof CONSTANTS.STORAGE.FILTER.members | typeof CONSTANTS.STORAGE.FILTER.specials;
6
+ export type ShapeConst = typeof CONSTANTS.SHAPES.formats | typeof CONSTANTS.SHAPES.types;
7
+ export type RoleConst = typeof CONSTANTS.SHAPES_PSEUDO.roles;
8
+ export type ResourceConst = typeof CONSTANTS.RESOURCES.resources;
9
+ export type StepConst = typeof CONSTANTS.STEP.work | typeof CONSTANTS.STEP.branch | typeof CONSTANTS.STEP.while | typeof CONSTANTS.STEP.for;
10
+ export type WorkflowConst = typeof CONSTANTS.WORKFLOW.workflow | typeof CONSTANTS.WORKFLOW.workflowSpec | typeof CONSTANTS.WORKFLOW.execution;
11
+ export interface DryRunManagerType {
12
+ dryRunMode: boolean;
13
+ delay: number;
14
+ drySocketMode: boolean;
15
+ }
16
+ export type Role = {
17
+ id: RoleIdJson;
18
+ } & RoleLiteralJson;
19
+ export type ShapeData = FormatDataJson | TypeDataJson;
20
+ export type ShapeMeta = FormatMetaJson | TypeMetaJson;
21
+ export type ShapeDataMap<T extends ShapeData> = Record<FilterConst, T[]>;
22
+ export type ShapeMetaMap<T extends ShapeMeta> = Record<FilterConst, T[]>;
23
+ export type ResourceMetaMap = Record<TypeIdJson, ResourceMetaJson[]>;
24
+ export type ResourceDataMap = Record<TypeIdJson, ResourceDataJson[]>;
25
+ export type ExternallyProvidedResourceMeta = {
26
+ id: ResourceIdJson;
27
+ typeId: TypeIdJson;
28
+ creationContext: {
29
+ roleId: RoleIdJson;
30
+ executionId: ExecutionIdJson;
31
+ };
32
+ };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@toolproof-npm/shared",
3
+ "version": "0.1.14",
4
+ "description": "Core library utilities for ToolProof",
5
+ "keywords": [
6
+ "toolproof",
7
+ "utilities",
8
+ "library"
9
+ ],
10
+ "author": "ToolProof Team",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/ToolProof/core.git",
15
+ "directory": "packages/_lib"
16
+ },
17
+ "homepage": "https://github.com/ToolProof/core#readme",
18
+ "bugs": {
19
+ "url": "https://github.com/ToolProof/core/issues"
20
+ },
21
+ "type": "module",
22
+ "main": "dist/index.js",
23
+ "types": "dist/index.d.ts",
24
+ "sideEffects": false,
25
+ "exports": {
26
+ ".": {
27
+ "import": "./dist/index.js",
28
+ "types": "./dist/index.d.ts"
29
+ },
30
+ "./constants": {
31
+ "import": "./dist/constants.js",
32
+ "types": "./dist/constants.d.ts"
33
+ },
34
+ "./types": {
35
+ "import": "./dist/types.js",
36
+ "types": "./dist/types.d.ts"
37
+ },
38
+ "./server": {
39
+ "node": "./dist/firestoreAdminHelpers.js",
40
+ "types": "./dist/firestoreAdminHelpers.d.ts"
41
+ }
42
+ },
43
+ "scripts": {
44
+ "build": "tsc -b"
45
+ },
46
+ "files": [
47
+ "dist",
48
+ "README.md"
49
+ ],
50
+ "devDependencies": {
51
+ "@google-cloud/storage": "^7.17.3",
52
+ "@types/node": "^20.19.25",
53
+ "json-schema-to-typescript": "^15.0.4",
54
+ "ts-node": "^10.9.2",
55
+ "typescript": "^5.9.3"
56
+ },
57
+ "dependencies": {
58
+ "@toolproof-npm/schema": "^0.1.12",
59
+ "firebase-admin": "^13.6.0"
60
+ }
61
+ }