@mikarinneoracle/oci-cdk-code-only-preview 0.0.37 → 0.0.38

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 CHANGED
@@ -127,16 +127,16 @@ export OCI_CLI_PATH="/Users/MRINNE/projects/ocdk/.tools/oci-preview-bin/oci"
127
127
  # Required: OCI target
128
128
  export OCI_COMPARTMENT_ID='ocid1.compartment.oc1...'
129
129
 
130
- # Required: handler. OCDK resolves the latest available Python runtime.
130
+ # Optional explicit code-only handler. OCDK converts the standard Python
131
+ # func.yaml entrypoint to func.handler automatically.
131
132
  # Optionally pin one: export OCI_CODE_ONLY_RUNTIME_NAME='python312.ol9'
132
- export OCI_FUNCTION_HANDLER='func.handler'
133
133
 
134
134
  # Required in func.yaml: name: my-function
135
135
  # Terraform creates the Function App; OCI CLI preview uploads the ZIP function
136
136
  npx ocdk deploy --auto-approve --code-only
137
137
  ```
138
138
 
139
- For a Node.js function, use the JavaScript file as the handler (not `fdk.handle` or `node func.js`):
139
+ For a Node.js function, use the JavaScript file as the handler (not `fdk.handle` or `node func.js`). OCDK resolves the runtime from `build_image` or `run_image` when present:
140
140
 
141
141
  ```bash
142
142
  export OCI_CODE_ONLY_RUNTIME_NAME='node24.ol9'
@@ -154,7 +154,7 @@ entrypoint: node func.js
154
154
 
155
155
  Keep `@fnproject/fdk` in `package.json` dependencies. The function source file uses `fdk.handle(...)`; it is not the OCI handler value.
156
156
 
157
- For Java, the code-only archive must contain exactly one fat/uber JAR at the ZIP root. Build it first and point OCDK to it when necessary:
157
+ For Java, the code-only archive must contain exactly one fat/uber JAR at the ZIP root. OCDK resolves the runtime from a `jdk`/`jre` version in `build_image` or `run_image` when present. Build it first and point OCDK to it when necessary:
158
158
 
159
159
  ```bash
160
160
  export OCI_CODE_ONLY_RUNTIME_NAME='java21.ol9'
@@ -173,7 +173,7 @@ OCDK also runs this build automatically when no artifact exists yet, and searche
173
173
 
174
174
  #### Find the available code-only runtimes
175
175
 
176
- The exact `OCI_CODE_ONLY_RUNTIME_NAME` values are enabled per tenancy and region during this Limited Availability preview. For Python, OCDK queries this list automatically. With `runtime: python`, it selects the version in `build_image` or `run_image` (for example `fnproject/python:3.12` selects `python312...`); without a versioned image, it selects the newest matching runtime. Set `OCI_CODE_ONLY_RUNTIME_NAME` to pin or override that choice. Query the Preview CLI to inspect available runtimes or when deploying another language:
176
+ The exact `OCI_CODE_ONLY_RUNTIME_NAME` values are enabled per tenancy and region during this Limited Availability preview. For Python, Node.js, and Java, OCDK queries this list automatically. With a plain runtime name, it selects the version in `build_image` or `run_image` (for example `fnproject/python:3.12` selects `python312...`, and `jdk17` selects `java17...`); without a versioned image, it selects the newest matching runtime. Set `OCI_CODE_ONLY_RUNTIME_NAME` to pin or override that choice. Query the Preview CLI to inspect available runtimes or when deploying another language:
177
177
 
178
178
  ```bash
179
179
  # List every runtime available to the active OCI profile
@@ -60,28 +60,37 @@ function listItems(result) {
60
60
  return [];
61
61
  }
62
62
 
63
- function pythonRuntimeSortKey(runtimeName) {
64
- const match = runtimeName.toLowerCase().match(/^python(\d+)/);
63
+ function runtimeLanguage(runtime) {
64
+ const normalized = runtime.toLowerCase().replace(/[^a-z0-9]/g, '');
65
+ return ['python', 'node', 'java'].find((language) => normalized.startsWith(language));
66
+ }
67
+
68
+ function runtimeSortKey(runtimeName, language) {
69
+ const match = runtimeName.toLowerCase().match(new RegExp(`^${language}(\\d+)`));
65
70
  return match ? Number.parseInt(match[1], 10) : -1;
66
71
  }
67
72
 
68
- function pythonRuntimePrefix(runtime, yaml) {
69
- // OCI's preview runtime names omit separators from the Python version:
70
- // func.yaml's "python3.12" therefore maps to the runtime-list prefix
71
- // "python312". For a plain "python", honor the version in Fn's
72
- // build_image/run_image before falling back to the newest available version.
73
+ function runtimePrefix(runtime, yaml) {
74
+ // OCI's preview runtime names omit separators from language versions, such
75
+ // as Python 3.12 -> python312. For a plain language name, honor the version
76
+ // in Fn's build_image/run_image before falling back to the newest runtime.
73
77
  const normalizedRuntime = runtime.toLowerCase().replace(/[^a-z0-9]/g, '');
74
- if (normalizedRuntime !== 'python') return normalizedRuntime;
78
+ const language = runtimeLanguage(runtime);
79
+ if (!language || normalizedRuntime !== language) return normalizedRuntime;
75
80
  for (const key of ['build_image', 'run_image']) {
76
81
  const image = yamlValue(yaml, key);
77
- const match = image.match(/(?:^|\/)python:(\d+)(?:\.(\d+))?(?:[-.]|$)/i);
78
- if (match) return `python${match[1]}${match[2] || ''}`;
82
+ const versionMatch = language === 'java'
83
+ ? image.match(/(?:jdk|jre|java)[-:]?(\d+)/i)
84
+ : image.match(new RegExp(`(?:^|/)${language}:(\\d+)(?:\\.(\\d+))?(?:[-.]|$)`, 'i'));
85
+ if (versionMatch) return `${language}${versionMatch[1]}${versionMatch[2] || ''}`;
79
86
  }
80
- return 'python';
87
+ return language;
81
88
  }
82
89
 
83
- function resolvePythonRuntime(runtime, yaml) {
84
- const namePrefix = pythonRuntimePrefix(runtime, yaml);
90
+ function resolveRuntime(runtime, yaml) {
91
+ const language = runtimeLanguage(runtime);
92
+ if (!language) return '';
93
+ const namePrefix = runtimePrefix(runtime, yaml);
85
94
  const result = jsonOci(['fn', 'runtime', 'list', '--all', '--name-starts-with', namePrefix]);
86
95
  const candidates = listItems(result)
87
96
  .map(runtimeResourceName)
@@ -90,7 +99,7 @@ function resolvePythonRuntime(runtime, yaml) {
90
99
  fail(`no available code-only runtime matches ${runtime}. Set OCI_CODE_ONLY_RUNTIME_NAME to a runtime returned by "oci fn runtime list --all".`);
91
100
  }
92
101
  candidates.sort((left, right) => {
93
- const versionDifference = pythonRuntimeSortKey(right) - pythonRuntimeSortKey(left);
102
+ const versionDifference = runtimeSortKey(right, language) - runtimeSortKey(left, language);
94
103
  return versionDifference || right.localeCompare(left);
95
104
  });
96
105
  const selected = candidates[0];
@@ -98,6 +107,13 @@ function resolvePythonRuntime(runtime, yaml) {
98
107
  return selected;
99
108
  }
100
109
 
110
+ function codeOnlyPythonHandler(handler) {
111
+ // Fn's generated container entrypoint is not a code-only handler. Convert
112
+ // the standard form to the handler syntax required by the managed runtime.
113
+ const match = handler.match(/^\/python\/bin\/fdk\s+\/function\/(.+?)\.py\s+([A-Za-z_][A-Za-z0-9_]*)$/);
114
+ return match ? `${match[1].replace(/[\\/]/g, '.')}.${match[2]}` : handler;
115
+ }
116
+
101
117
  function readFunctionMetadata() {
102
118
  const funcYamlPath = path.join(projectDir, 'func.yaml');
103
119
  const yaml = fs.existsSync(funcYamlPath) ? fs.readFileSync(funcYamlPath, 'utf8') : '';
@@ -105,19 +121,21 @@ function readFunctionMetadata() {
105
121
  const appName = (process.env.OCI_FUNCTION_APP_NAME || functionName).trim();
106
122
  const configuredRuntime = yamlValue(yaml, 'runtime');
107
123
  const runtimeName = (process.env.OCI_CODE_ONLY_RUNTIME_NAME || '').trim()
108
- || (configuredRuntime.toLowerCase().startsWith('python') ? resolvePythonRuntime(configuredRuntime, yaml) : '');
124
+ || resolveRuntime(configuredRuntime, yaml);
109
125
  const configuredHandler = (process.env.OCI_FUNCTION_HANDLER || yamlValue(yaml, 'cmd') || yamlValue(yaml, 'entrypoint')).trim();
110
126
  // The managed Node runtime already invokes `node`; its handler is the script
111
127
  // path, whereas a conventional func.yaml entrypoint is `node func.js`.
112
128
  const handler = runtimeName.toLowerCase().startsWith('node')
113
129
  ? configuredHandler.replace(/^node\s+/, '')
130
+ : runtimeName.toLowerCase().startsWith('python')
131
+ ? codeOnlyPythonHandler(configuredHandler)
114
132
  : configuredHandler;
115
133
  const memory = integerValue(process.env.OCI_FUNCTION_MEMORY_MB || yamlValue(yaml, 'memory'), 'OCI_FUNCTION_MEMORY_MB', 256);
116
134
  const timeout = integerValue(process.env.OCI_FUNCTION_TIMEOUT_SECONDS || yamlValue(yaml, 'timeout'), 'OCI_FUNCTION_TIMEOUT_SECONDS', 30);
117
135
 
118
136
  if (!functionName) fail('set OCI_FUNCTION_NAME or add name: to func.yaml.');
119
137
  if (!appName) fail('set OCI_FUNCTION_APP_NAME.');
120
- if (!runtimeName) fail('set OCI_CODE_ONLY_RUNTIME_NAME (for example python312.ol9). Automatic runtime resolution currently supports Python functions with runtime: python in func.yaml.');
138
+ if (!runtimeName) fail('set OCI_CODE_ONLY_RUNTIME_NAME (for example python312.ol9). Automatic runtime resolution supports Python, Node.js, and Java func.yaml runtimes.');
121
139
  if (!handler) fail('set OCI_FUNCTION_HANDLER or add cmd: to func.yaml.');
122
140
 
123
141
  return { functionName, appName, handler, runtimeName, memory, timeout };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikarinneoracle/oci-cdk-code-only-preview",
3
- "version": "0.0.37",
3
+ "version": "0.0.38",
4
4
  "description": "OCI CDK stack for OCI Functions, API Gateway, and related infrastructure",
5
5
  "main": "lib/index.js",
6
6
  "bin": {