@ace-sdk/core 1.0.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.
Files changed (86) hide show
  1. package/README.md +54 -0
  2. package/dist/cache/index.d.ts +8 -0
  3. package/dist/cache/index.d.ts.map +1 -0
  4. package/dist/cache/index.js +6 -0
  5. package/dist/cache/index.js.map +1 -0
  6. package/dist/cache/local-cache.d.ts +72 -0
  7. package/dist/cache/local-cache.d.ts.map +1 -0
  8. package/dist/cache/local-cache.js +227 -0
  9. package/dist/cache/local-cache.js.map +1 -0
  10. package/dist/cache/session-storage.d.ts +76 -0
  11. package/dist/cache/session-storage.d.ts.map +1 -0
  12. package/dist/cache/session-storage.js +237 -0
  13. package/dist/cache/session-storage.js.map +1 -0
  14. package/dist/client/ace-client.d.ts +199 -0
  15. package/dist/client/ace-client.d.ts.map +1 -0
  16. package/dist/client/ace-client.js +454 -0
  17. package/dist/client/ace-client.js.map +1 -0
  18. package/dist/client/index.d.ts +6 -0
  19. package/dist/client/index.d.ts.map +1 -0
  20. package/dist/client/index.js +5 -0
  21. package/dist/client/index.js.map +1 -0
  22. package/dist/config/context.d.ts +48 -0
  23. package/dist/config/context.d.ts.map +1 -0
  24. package/dist/config/context.js +147 -0
  25. package/dist/config/context.js.map +1 -0
  26. package/dist/config/helpers.d.ts +79 -0
  27. package/dist/config/helpers.d.ts.map +1 -0
  28. package/dist/config/helpers.js +173 -0
  29. package/dist/config/helpers.js.map +1 -0
  30. package/dist/config/index.d.ts +10 -0
  31. package/dist/config/index.d.ts.map +1 -0
  32. package/dist/config/index.js +9 -0
  33. package/dist/config/index.js.map +1 -0
  34. package/dist/config/loader.d.ts +58 -0
  35. package/dist/config/loader.d.ts.map +1 -0
  36. package/dist/config/loader.js +275 -0
  37. package/dist/config/loader.js.map +1 -0
  38. package/dist/config/migration.d.ts +29 -0
  39. package/dist/config/migration.d.ts.map +1 -0
  40. package/dist/config/migration.js +137 -0
  41. package/dist/config/migration.js.map +1 -0
  42. package/dist/config/xdg.d.ts +62 -0
  43. package/dist/config/xdg.d.ts.map +1 -0
  44. package/dist/config/xdg.js +168 -0
  45. package/dist/config/xdg.js.map +1 -0
  46. package/dist/index.d.ts +32 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +50 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/logger/index.d.ts +6 -0
  51. package/dist/logger/index.d.ts.map +1 -0
  52. package/dist/logger/index.js +5 -0
  53. package/dist/logger/index.js.map +1 -0
  54. package/dist/logger/interface.d.ts +73 -0
  55. package/dist/logger/interface.d.ts.map +1 -0
  56. package/dist/logger/interface.js +11 -0
  57. package/dist/logger/interface.js.map +1 -0
  58. package/dist/logger/noop.d.ts +32 -0
  59. package/dist/logger/noop.d.ts.map +1 -0
  60. package/dist/logger/noop.js +53 -0
  61. package/dist/logger/noop.js.map +1 -0
  62. package/dist/types/config.d.ts +94 -0
  63. package/dist/types/config.d.ts.map +1 -0
  64. package/dist/types/config.js +26 -0
  65. package/dist/types/config.js.map +1 -0
  66. package/dist/types/index.d.ts +8 -0
  67. package/dist/types/index.d.ts.map +1 -0
  68. package/dist/types/index.js +6 -0
  69. package/dist/types/index.js.map +1 -0
  70. package/dist/types/pattern.d.ts +246 -0
  71. package/dist/types/pattern.d.ts.map +1 -0
  72. package/dist/types/pattern.js +22 -0
  73. package/dist/types/pattern.js.map +1 -0
  74. package/dist/utils/code-extractor.d.ts +34 -0
  75. package/dist/utils/code-extractor.d.ts.map +1 -0
  76. package/dist/utils/code-extractor.js +116 -0
  77. package/dist/utils/code-extractor.js.map +1 -0
  78. package/dist/utils/index.d.ts +8 -0
  79. package/dist/utils/index.d.ts.map +1 -0
  80. package/dist/utils/index.js +6 -0
  81. package/dist/utils/index.js.map +1 -0
  82. package/dist/utils/semver.d.ts +41 -0
  83. package/dist/utils/semver.d.ts.map +1 -0
  84. package/dist/utils/semver.js +90 -0
  85. package/dist/utils/semver.js.map +1 -0
  86. package/package.json +58 -0
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Context Creation and Resolution
3
+ * @package @ace-sdk/core
4
+ */
5
+ import { isatty } from 'tty';
6
+ import { DEFAULT_RUNTIME_SETTINGS } from '../types/config.js';
7
+ import { loadConfig } from './loader.js';
8
+ import { getTokenForOrg } from './helpers.js';
9
+ /**
10
+ * Checks if running in an interactive terminal
11
+ */
12
+ function isInteractive() {
13
+ return isatty(process.stdout.fd) && isatty(process.stdin.fd);
14
+ }
15
+ /**
16
+ * Resolves org and project context using 3-tier precedence:
17
+ *
18
+ * 1. CLI flags (--org, --project) - HIGHEST PRIORITY
19
+ * 2. Environment variables (ACE_ORG_ID, ACE_PROJECT_ID)
20
+ * 3. Error - NO CONTEXT FOUND
21
+ *
22
+ * Note: .claude/settings.json is NOT read by this function. That's Claude Code's job.
23
+ * Claude Code reads .claude/settings.json and sets ACE_ORG_ID/ACE_PROJECT_ID as ENV vars.
24
+ *
25
+ * @param options - CLI flags and working directory
26
+ * @returns Resolved org and project IDs with source
27
+ * @throws Error if no context can be resolved
28
+ */
29
+ export function resolveContext(options = {}) {
30
+ // Tier 1: CLI flags (highest priority)
31
+ if (options.org && options.project) {
32
+ return {
33
+ orgId: options.org,
34
+ projectId: options.project,
35
+ source: 'flags'
36
+ };
37
+ }
38
+ // Partial flags - need to combine with other sources
39
+ let orgId = options.org;
40
+ let projectId = options.project;
41
+ let source = 'flags';
42
+ // Tier 2: Environment variables (set by Claude Code from .claude/settings.json)
43
+ if (!orgId && process.env.ACE_ORG_ID) {
44
+ orgId = process.env.ACE_ORG_ID;
45
+ source = 'env';
46
+ }
47
+ if (!projectId && process.env.ACE_PROJECT_ID) {
48
+ projectId = process.env.ACE_PROJECT_ID;
49
+ if (!orgId)
50
+ source = 'env'; // Only change source if no flags used
51
+ }
52
+ // Final check: do we have both?
53
+ if (orgId && projectId) {
54
+ return { orgId, projectId, source };
55
+ }
56
+ // Tier 3: Error - no context found
57
+ const interactive = isInteractive();
58
+ const missing = [];
59
+ if (!orgId)
60
+ missing.push('organization ID');
61
+ if (!projectId)
62
+ missing.push('project ID');
63
+ let errorMessage = `Could not resolve ${missing.join(' and ')}.\n\n`;
64
+ if (interactive) {
65
+ errorMessage += `Please use one of the following methods:\n\n`;
66
+ errorMessage += `1. Use CLI flags:\n`;
67
+ errorMessage += ` ce-ace <command> --org org_xxx --project prj_xxx\n\n`;
68
+ errorMessage += `2. Set environment variables:\n`;
69
+ errorMessage += ` export ACE_ORG_ID=org_xxx\n`;
70
+ errorMessage += ` export ACE_PROJECT_ID=prj_xxx\n\n`;
71
+ errorMessage += `3. Run configuration wizard:\n`;
72
+ errorMessage += ` ce-ace config\n`;
73
+ errorMessage += ` (This helps set up ~/.config/ace/config.json with org tokens)\n\n`;
74
+ errorMessage += `Note: If using Claude Code, set ACE_ORG_ID and ACE_PROJECT_ID in .claude/settings.json:\n`;
75
+ errorMessage += ` {\n`;
76
+ errorMessage += ` "env": {\n`;
77
+ errorMessage += ` "ACE_ORG_ID": "org_xxx",\n`;
78
+ errorMessage += ` "ACE_PROJECT_ID": "prj_xxx"\n`;
79
+ errorMessage += ` }\n`;
80
+ errorMessage += ` }\n`;
81
+ }
82
+ else {
83
+ // Non-interactive (hooks, CI)
84
+ errorMessage += `Running in non-interactive mode (hook or CI).\n\n`;
85
+ errorMessage += `Set ACE_ORG_ID and ACE_PROJECT_ID environment variables, or use --org and --project flags.\n`;
86
+ }
87
+ throw new Error(errorMessage);
88
+ }
89
+ /**
90
+ * Validates that an org ID matches the expected format
91
+ */
92
+ export function isValidOrgId(orgId) {
93
+ return /^org_[a-zA-Z0-9_-]+$/.test(orgId);
94
+ }
95
+ /**
96
+ * Validates that a project ID matches the expected format
97
+ */
98
+ export function isValidProjectId(projectId) {
99
+ return /^prj_[a-f0-9]+$/.test(projectId);
100
+ }
101
+ /**
102
+ * Create AceContext from CLI flags, environment, and config files
103
+ *
104
+ * This function implements the complete context resolution flow:
105
+ * 1. Resolve org/project using 4-tier precedence (flags > env > .claude/settings.json > error)
106
+ * 2. Load global config to get server URL and tokens
107
+ * 3. Get the correct token for the resolved organization
108
+ * 4. Merge with server-derived runtime settings
109
+ *
110
+ * @param options - CLI flags for org/project override
111
+ * @param serverConfig - Optional server configuration (fetched via ACEServerClient.getConfig())
112
+ * @param configOverrides - Optional config overrides
113
+ * @param logger - Optional logger
114
+ * @returns Complete runtime context with merged settings
115
+ * @throws Error if context cannot be resolved
116
+ */
117
+ export async function createContext(options = {}, serverConfig, configOverrides, logger) {
118
+ // Step 1: Resolve org and project IDs using precedence chain
119
+ const resolved = resolveContext(options);
120
+ const { orgId, projectId } = resolved;
121
+ // Step 2: Load global config
122
+ const globalConfig = loadConfig(configOverrides, logger);
123
+ // Step 3: Get the correct API token for this organization
124
+ const apiToken = getTokenForOrg(globalConfig, orgId);
125
+ // Step 4: Merge server runtime settings with defaults
126
+ const runtimeSettings = {
127
+ ...DEFAULT_RUNTIME_SETTINGS,
128
+ ...(serverConfig?.runtime_settings || {})
129
+ };
130
+ // Step 5: Override with environment variables if present
131
+ if (process.env.ACE_SEARCH_THRESHOLD) {
132
+ runtimeSettings.searchThreshold = parseFloat(process.env.ACE_SEARCH_THRESHOLD);
133
+ }
134
+ if (process.env.ACE_LEARNING_ENABLED) {
135
+ runtimeSettings.learningEnabled = process.env.ACE_LEARNING_ENABLED === 'true';
136
+ }
137
+ // Step 6: Return complete context
138
+ return {
139
+ serverUrl: globalConfig.serverUrl,
140
+ apiToken,
141
+ projectId,
142
+ orgId,
143
+ cacheTtlMinutes: globalConfig.cacheTtlMinutes,
144
+ runtimeSettings
145
+ };
146
+ }
147
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/config/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Configuration Helper Functions
3
+ * @package @ace-sdk/core
4
+ */
5
+ import { AceConfig } from '../types/config.js';
6
+ /**
7
+ * Gets the API token for a specific organization
8
+ *
9
+ * In multi-org mode: Looks up token by org ID in config.orgs
10
+ * In single-org mode: Returns root-level apiToken
11
+ *
12
+ * @param config - ACE configuration
13
+ * @param orgId - Organization ID (e.g., org_34fYIl...)
14
+ * @returns API token for the organization
15
+ * @throws Error if no token found for the specified org
16
+ */
17
+ export declare function getTokenForOrg(config: AceConfig, orgId: string): string;
18
+ /**
19
+ * Gets the organization name for display purposes
20
+ *
21
+ * @param config - ACE configuration
22
+ * @param orgId - Organization ID
23
+ * @returns Organization name or the org ID if name not found
24
+ */
25
+ export declare function getOrgName(config: AceConfig, orgId: string): string;
26
+ /**
27
+ * Lists all configured organizations
28
+ *
29
+ * @param config - ACE configuration
30
+ * @returns Array of { orgId, orgName, projectCount }
31
+ */
32
+ export declare function listOrganizations(config: AceConfig): Array<{
33
+ orgId: string;
34
+ orgName: string;
35
+ projectCount: number;
36
+ }>;
37
+ /**
38
+ * Checks if a project belongs to a specific organization
39
+ *
40
+ * @param config - ACE configuration
41
+ * @param orgId - Organization ID
42
+ * @param projectId - Project ID
43
+ * @returns true if the project belongs to the org, false otherwise
44
+ */
45
+ export declare function projectBelongsToOrg(config: AceConfig, orgId: string, projectId: string): boolean;
46
+ /**
47
+ * Extracts organization ID from an API token
48
+ *
49
+ * ACE tokens have format: ace_{orgId8chars}{random}
50
+ * Example: ace_34fYIlitYk4nyFuTvtsAzA6uUJF
51
+ * → org_34fYIlit
52
+ *
53
+ * @param token - API token
54
+ * @returns Organization ID or null if can't extract
55
+ */
56
+ export declare function extractOrgIdFromToken(token: string): string | null;
57
+ /**
58
+ * Gets all projects for a specific organization
59
+ *
60
+ * @param config - ACE configuration
61
+ * @param orgId - Organization ID
62
+ * @returns Array of project IDs
63
+ */
64
+ export declare function getProjectsForOrg(config: AceConfig, orgId: string): string[];
65
+ /**
66
+ * Checks if the configuration is in multi-org mode
67
+ *
68
+ * @param config - ACE configuration
69
+ * @returns true if multi-org mode is active
70
+ */
71
+ export declare function isMultiOrgMode(config: AceConfig): boolean;
72
+ /**
73
+ * Validates configuration completeness
74
+ *
75
+ * @param config - ACE configuration
76
+ * @returns Array of validation error messages (empty if valid)
77
+ */
78
+ export declare function validateConfig(config: AceConfig): string[];
79
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/config/helpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA4BvE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,CAAC;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAuBD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,GAChB,OAAO,CAQT;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAalE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAK5E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,CA6B1D"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Configuration Helper Functions
3
+ * @package @ace-sdk/core
4
+ */
5
+ /**
6
+ * Gets the API token for a specific organization
7
+ *
8
+ * In multi-org mode: Looks up token by org ID in config.orgs
9
+ * In single-org mode: Returns root-level apiToken
10
+ *
11
+ * @param config - ACE configuration
12
+ * @param orgId - Organization ID (e.g., org_34fYIl...)
13
+ * @returns API token for the organization
14
+ * @throws Error if no token found for the specified org
15
+ */
16
+ export function getTokenForOrg(config, orgId) {
17
+ // Multi-org mode: Look up token by org ID
18
+ if (config.orgs && config.orgs[orgId]) {
19
+ return config.orgs[orgId].apiToken;
20
+ }
21
+ // Single-org mode: Fall back to root-level token
22
+ if (config.apiToken) {
23
+ return config.apiToken;
24
+ }
25
+ // No token found
26
+ throw new Error(`No API token found for organization ${orgId}.\n\n` +
27
+ `This organization is not configured in ~/.config/ace/config.json.\n\n` +
28
+ `To fix this:\n` +
29
+ `1. Run: ce-ace config\n` +
30
+ `2. Or add the organization manually to ~/.config/ace/config.json:\n\n` +
31
+ `{\n` +
32
+ ` "orgs": {\n` +
33
+ ` "${orgId}": {\n` +
34
+ ` "orgName": "Your Org Name",\n` +
35
+ ` "apiToken": "ace_xxx...",\n` +
36
+ ` "projects": ["prj_xxx..."]\n` +
37
+ ` }\n` +
38
+ ` }\n` +
39
+ `}\n`);
40
+ }
41
+ /**
42
+ * Gets the organization name for display purposes
43
+ *
44
+ * @param config - ACE configuration
45
+ * @param orgId - Organization ID
46
+ * @returns Organization name or the org ID if name not found
47
+ */
48
+ export function getOrgName(config, orgId) {
49
+ if (config.orgs && config.orgs[orgId]) {
50
+ return config.orgs[orgId].orgName || orgId;
51
+ }
52
+ return orgId;
53
+ }
54
+ /**
55
+ * Lists all configured organizations
56
+ *
57
+ * @param config - ACE configuration
58
+ * @returns Array of { orgId, orgName, projectCount }
59
+ */
60
+ export function listOrganizations(config) {
61
+ const orgs = [];
62
+ if (config.orgs) {
63
+ // Multi-org mode
64
+ for (const [orgId, orgConfig] of Object.entries(config.orgs)) {
65
+ orgs.push({
66
+ orgId,
67
+ orgName: orgConfig.orgName || orgId,
68
+ projectCount: orgConfig.projects?.length || 0
69
+ });
70
+ }
71
+ }
72
+ else if (config.apiToken) {
73
+ // Single-org mode - try to extract org ID from token
74
+ const orgId = extractOrgIdFromToken(config.apiToken);
75
+ orgs.push({
76
+ orgId: orgId || 'default',
77
+ orgName: 'Default Organization',
78
+ projectCount: 0
79
+ });
80
+ }
81
+ return orgs;
82
+ }
83
+ /**
84
+ * Checks if a project belongs to a specific organization
85
+ *
86
+ * @param config - ACE configuration
87
+ * @param orgId - Organization ID
88
+ * @param projectId - Project ID
89
+ * @returns true if the project belongs to the org, false otherwise
90
+ */
91
+ export function projectBelongsToOrg(config, orgId, projectId) {
92
+ if (config.orgs && config.orgs[orgId]) {
93
+ const projects = config.orgs[orgId].projects || [];
94
+ return projects.includes(projectId);
95
+ }
96
+ // In single-org mode, assume any project is valid
97
+ return true;
98
+ }
99
+ /**
100
+ * Extracts organization ID from an API token
101
+ *
102
+ * ACE tokens have format: ace_{orgId8chars}{random}
103
+ * Example: ace_34fYIlitYk4nyFuTvtsAzA6uUJF
104
+ * → org_34fYIlit
105
+ *
106
+ * @param token - API token
107
+ * @returns Organization ID or null if can't extract
108
+ */
109
+ export function extractOrgIdFromToken(token) {
110
+ if (!token.startsWith('ace_')) {
111
+ return null;
112
+ }
113
+ // Extract first 8 chars after 'ace_'
114
+ const orgIdPart = token.substring(4, 12);
115
+ if (orgIdPart.length === 8) {
116
+ return `org_${orgIdPart}`;
117
+ }
118
+ return null;
119
+ }
120
+ /**
121
+ * Gets all projects for a specific organization
122
+ *
123
+ * @param config - ACE configuration
124
+ * @param orgId - Organization ID
125
+ * @returns Array of project IDs
126
+ */
127
+ export function getProjectsForOrg(config, orgId) {
128
+ if (config.orgs && config.orgs[orgId]) {
129
+ return config.orgs[orgId].projects || [];
130
+ }
131
+ return [];
132
+ }
133
+ /**
134
+ * Checks if the configuration is in multi-org mode
135
+ *
136
+ * @param config - ACE configuration
137
+ * @returns true if multi-org mode is active
138
+ */
139
+ export function isMultiOrgMode(config) {
140
+ return !!(config.orgs && Object.keys(config.orgs).length > 0);
141
+ }
142
+ /**
143
+ * Validates configuration completeness
144
+ *
145
+ * @param config - ACE configuration
146
+ * @returns Array of validation error messages (empty if valid)
147
+ */
148
+ export function validateConfig(config) {
149
+ const errors = [];
150
+ // Check server URL
151
+ if (!config.serverUrl) {
152
+ errors.push('Missing serverUrl in configuration');
153
+ }
154
+ // Check authentication
155
+ const hasMultiOrg = config.orgs && Object.keys(config.orgs).length > 0;
156
+ const hasSingleOrg = !!config.apiToken;
157
+ if (!hasMultiOrg && !hasSingleOrg) {
158
+ errors.push('No API token configured (neither multi-org nor single-org mode)');
159
+ }
160
+ // Validate multi-org structure
161
+ if (hasMultiOrg && config.orgs) {
162
+ for (const [orgId, orgConfig] of Object.entries(config.orgs)) {
163
+ if (!orgConfig.apiToken) {
164
+ errors.push(`Organization ${orgId} is missing apiToken`);
165
+ }
166
+ if (!orgId.startsWith('org_')) {
167
+ errors.push(`Invalid organization ID format: ${orgId} (should start with 'org_')`);
168
+ }
169
+ }
170
+ }
171
+ return errors;
172
+ }
173
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/config/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Config exports for @ace-sdk/core
3
+ */
4
+ export { loadConfig, getConfigPath, isConfigured } from './loader.js';
5
+ export type { ConfigOverrides, LoadConfigResult } from './loader.js';
6
+ export { expandPath, autodiscoverConfigPath, getLegacyConfigPath, getXdgConfigPath, autoMigrateConfig, ensureConfigDirectory, setSecurePermissions } from './xdg.js';
7
+ export { migrateConfig, checkAndMigrate, autoMigrate } from './migration.js';
8
+ export { getTokenForOrg, getOrgName, listOrganizations, projectBelongsToOrg, extractOrgIdFromToken, getProjectsForOrg, isMultiOrgMode, validateConfig } from './helpers.js';
9
+ export { resolveContext, isValidOrgId, isValidProjectId, createContext } from './context.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrK,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5K,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Config exports for @ace-sdk/core
3
+ */
4
+ export { loadConfig, getConfigPath, isConfigured } from './loader.js';
5
+ export { expandPath, autodiscoverConfigPath, getLegacyConfigPath, getXdgConfigPath, autoMigrateConfig, ensureConfigDirectory, setSecurePermissions } from './xdg.js';
6
+ export { migrateConfig, checkAndMigrate, autoMigrate } from './migration.js';
7
+ export { getTokenForOrg, getOrgName, listOrganizations, projectBelongsToOrg, extractOrgIdFromToken, getProjectsForOrg, isMultiOrgMode, validateConfig } from './helpers.js';
8
+ export { resolveContext, isValidOrgId, isValidProjectId, createContext } from './context.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrK,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC5K,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Configuration Loader - Core Logic
3
+ *
4
+ * Loads ACE configuration from multiple sources with priority order:
5
+ * 1. Override options (passed by caller, e.g., from CLI args)
6
+ * 2. Environment variables: ACE_CONFIG_PATH, ACE_PROJECT_ID
7
+ * 3. Config file (autodiscovered or specified)
8
+ * 4. Default values (lowest)
9
+ *
10
+ * XDG Base Directory Specification:
11
+ * - Default: ~/.config/ace/config.json
12
+ * - Legacy: ~/.ace/config.json (auto-migrated with backup)
13
+ *
14
+ * @package @ace-sdk/core
15
+ */
16
+ import type { AceConfig } from '../types/config.js';
17
+ import type { ILogger } from '../logger/index.js';
18
+ /**
19
+ * Options to override configuration values
20
+ * Typically populated from CLI arguments
21
+ */
22
+ export interface ConfigOverrides {
23
+ configPath?: string;
24
+ serverUrl?: string;
25
+ apiToken?: string;
26
+ projectId?: string;
27
+ orgId?: string;
28
+ cacheTtlMinutes?: number;
29
+ }
30
+ /**
31
+ * Extended result that includes resolved org info
32
+ */
33
+ export interface LoadConfigResult {
34
+ config: AceConfig;
35
+ resolvedOrgId?: string;
36
+ resolvedOrgName?: string;
37
+ }
38
+ /**
39
+ * Load configuration with priority:
40
+ * 1. Override options (from caller)
41
+ * 2. Environment variables: ACE_CONFIG_PATH, ACE_PROJECT_ID
42
+ * 3. Config file (autodiscovered via XDG or specified)
43
+ * 4. Default values (lowest)
44
+ *
45
+ * @param overrides - Optional configuration overrides (typically from CLI args)
46
+ * @param logger - Optional logger for output
47
+ * @returns Loaded configuration
48
+ */
49
+ export declare function loadConfig(overrides?: ConfigOverrides, logger?: ILogger): AceConfig;
50
+ /**
51
+ * Get config file path
52
+ */
53
+ export declare function getConfigPath(): string;
54
+ /**
55
+ * Check if configuration is complete
56
+ */
57
+ export declare function isConfigured(overrides?: ConfigOverrides, logger?: ILogger): boolean;
58
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGlD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,SAAS,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAiED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,SAAS,GAAE,eAAoB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAmLvF;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,GAAE,eAAoB,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAGvF"}